Avastage JavaScripti Proxy täiustatud mustreid objektide pealtkuulamiseks, valideerimiseks ja dünaamiliseks käitumiseks. Õppige, kuidas parandada koodi kvaliteeti, turvalisust ja hooldatavust.
JavaScripti Proxy mustrid: täiustatud objektide pealtkuulamine ja valideerimine
JavaScripti Proxy objekt on võimas funktsioon, mis võimaldab pealt kuulata ja kohandada objekti põhioperatsioone. See võimaldab täiustatud metaprogrammeerimise tehnikaid, pakkudes suuremat kontrolli objekti käitumise üle ja avades võimalusi keerukate disainimustrite jaoks. See artikkel uurib erinevaid Proxy mustreid, tutvustades nende kasutusjuhtumeid valideerimisel, pealtkuulamisel ja dünaamilisel käitumise muutmisel. Süveneme praktilistesse näidetesse, et demonstreerida, kuidas Proxyd saavad teie JavaScripti projektides parandada koodi kvaliteeti, turvalisust ja hooldatavust.
JavaScripti Proxy mõistmine
Oma olemuselt ümbritseb Proxy objekt teist objekti (sihtmärki) ja kuulab pealt sellel sihtmärgil sooritatud operatsioone. Neid pealtkuulamisi haldavad püüdurid (traps), mis on meetodid, mis määravad kohandatud käitumise konkreetsete operatsioonide jaoks, nagu omaduse hankimine, omaduse määramine või funktsiooni kutsumine. Proxy API pakub paindlikku ja laiendatavat mehhanismi objektide vaikekäitumise muutmiseks.
Põhimõisted
- Sihtmärk (Target): Algne objekt, mida Proxy ümbritseb.
- Käsitleja (Handler): Objekt, mis sisaldab püüduri meetodeid. Iga püüdur vastab konkreetsele operatsioonile.
- Püüdurid (Traps): Käsitleja sees olevad meetodid, mis kuulavad pealt ja kohandavad objekti operatsioone. Levinud püüdurid on näiteks
get,set,applyjaconstruct.
Proxy loomine
Proxy loomiseks kasutate konstruktorit Proxy, edastades argumentidena sihtmärkobjekti ja käsitleja objekti:
const target = {};
const handler = {
get: function(target, property, receiver) {
console.log(`Omaduse hankimine: ${property}`);
return Reflect.get(target, property, receiver);
}
};
const proxy = new Proxy(target, handler);
proxy.name = "John";
console.log(proxy.name); // Logib: Omaduse hankimine: name, seejärel John
Levinud Proxy püüdurid
Proxyd pakuvad mitmesuguseid püüdureid erinevate operatsioonide pealtkuulamiseks. Siin on mõned kõige sagedamini kasutatavad püüdurid:
get(target, property, receiver): Kuulab pealt omadusele juurdepääsu.set(target, property, value, receiver): Kuulab pealt omaduse määramist.has(target, property): Kuulab pealt operaatoritin.deleteProperty(target, property): Kuulab pealt operaatoritdelete.apply(target, thisArg, argumentsList): Kuulab pealt funktsioonikutseid.construct(target, argumentsList, newTarget): Kuulab pealt operaatoritnew.getPrototypeOf(target): Kuulab pealt meetoditObject.getPrototypeOf().setPrototypeOf(target, prototype): Kuulab pealt meetoditObject.setPrototypeOf().isExtensible(target): Kuulab pealt meetoditObject.isExtensible().preventExtensions(target): Kuulab pealt meetoditObject.preventExtensions().getOwnPropertyDescriptor(target, property): Kuulab pealt meetoditObject.getOwnPropertyDescriptor().defineProperty(target, property, descriptor): Kuulab pealt meetoditObject.defineProperty().ownKeys(target): Kuulab pealt meetodeidObject.getOwnPropertyNames()jaObject.getOwnPropertySymbols().
Proxy mustrid
Nüüd uurime mõningaid praktilisi Proxy mustreid ja nende rakendusi:
1. Valideeriv Proxy
Valideeriv Proxy rakendab piiranguid omaduste määramisel. See kuulab pealt püüdurit set, et valideerida uus väärtus enne määramise lubamist.
Näide: Kasutaja sisendi valideerimine vormis.
const user = {};
const validator = {
set: function(target, property, value) {
if (property === 'age') {
if (!Number.isInteger(value) || value < 0 || value > 120) {
throw new Error('Vigane vanus. Vanus peab olema täisarv vahemikus 0 kuni 120.');
}
}
target[property] = value;
return true; // Näitab õnnestumist
}
};
const proxy = new Proxy(user, validator);
proxy.name = 'Alice';
proxy.age = 30;
console.log(user);
try {
proxy.age = 'invalid'; // Visatakse viga
} catch (error) {
console.error(error.message);
}
Selles näites kontrollib set püüdur, kas omadus age on täisarv vahemikus 0 kuni 120. Kui valideerimine ebaõnnestub, visatakse viga, mis takistab vale väärtuse määramist.
Globaalne näide: See valideerimismuster on hädavajalik andmete terviklikkuse tagamiseks globaalsetes rakendustes, kus kasutaja sisend võib pärineda erinevatest allikatest ja kultuuridest. Näiteks postiindeksite valideerimine võib riigiti oluliselt erineda. Valideerivat proxyt saab kohandada toetama erinevaid valideerimisreegleid vastavalt kasutaja asukohale.
const address = {};
const addressValidator = {
set: function(target, property, value) {
if (property === 'postalCode') {
// Näide: Eeldades lihtsat USA postiindeksi valideerimist
if (!/^[0-9]{5}(?:-[0-9]{4})?$/.test(value)) {
throw new Error('Vigane USA postiindeks.');
}
}
target[property] = value;
return true;
}
};
const addressProxy = new Proxy(address, addressValidator);
addressProxy.postalCode = "12345-6789"; // Kehtiv
try {
addressProxy.postalCode = "abcde"; // Kehtetu
} catch(e) {
console.log(e);
}
// Rahvusvahelisema rakenduse jaoks kasutaksite keerukamat valideerimisteeki,
// mis suudaks valideerida postiindekseid vastavalt kasutaja riigile.
2. Logiv Proxy
Logiv Proxy kuulab pealt omadustele juurdepääsu ja nende määramist, et neid operatsioone logida. See on kasulik silumiseks ja auditeerimiseks.
Näide: Omadustele juurdepääsu ja nende muutmise logimine.
const data = {
value: 10
};
const logger = {
get: function(target, property) {
console.log(`Omaduse hankimine: ${property}`);
return target[property];
},
set: function(target, property, value) {
console.log(`Omaduse määramine: ${property} väärtusele ${value}`);
target[property] = value;
return true;
}
};
const proxy = new Proxy(data, logger);
console.log(proxy.value); // Logib: Omaduse hankimine: value, seejärel 10
proxy.value = 20; // Logib: Omaduse määramine: value väärtusele 20
Püüdurid get ja set logivad omadust, millele juurde pääsetakse või mida muudetakse, pakkudes jälge objekti interaktsioonidest.
Globaalne näide: Rahvusvahelises korporatsioonis saab logivaid proxy'sid kasutada andmetele juurdepääsu ja muudatuste auditeerimiseks, mida teevad töötajad erinevates asukohtades. See on oluline vastavuse ja turvalisuse tagamiseks. Logiinfos võib olla vaja arvestada ajavöönditega.
const employeeData = {
name: "John Doe",
salary: 50000
};
const auditLogger = {
get: function(target, property) {
const timestamp = new Date().toISOString();
console.log(`${timestamp} - [GET] Juurdepääs omadusele: ${property}`);
return target[property];
},
set: function(target, property, value) {
const timestamp = new Date().toISOString();
console.log(`${timestamp} - [SET] Omaduse määramine: ${property} väärtusele ${value}`);
target[property] = value;
return true;
}
};
const proxiedEmployee = new Proxy(employeeData, auditLogger);
proxiedEmployee.name; // Logib ajatempli ja juurdepääsu omadusele 'name'
proxiedEmployee.salary = 60000; // Logib ajatempli ja omaduse 'salary' muutmise
3. Kirjutuskaitstud Proxy
Kirjutuskaitstud Proxy takistab omaduste määramist. See kuulab pealt püüdurit set ja viskab vea, kui üritatakse omadust muuta.
Näide: Objekti muutumatuks tegemine.
const config = {
apiUrl: 'https://api.example.com'
};
const readOnly = {
set: function(target, property, value) {
throw new Error(`Omadust ei saa määrata: ${property}. Objekt on kirjutuskaitstud.`);
}
};
const proxy = new Proxy(config, readOnly);
console.log(proxy.apiUrl);
try {
proxy.apiUrl = 'https://newapi.example.com'; // Visatakse viga
} catch (error) {
console.error(error.message);
}
Iga katse määrata proxyle omadust põhjustab vea, tagades, et objekt jääb muutumatuks.
Globaalne näide: See muster on kasulik konfiguratsioonifailide kaitsmiseks, mida ei tohiks käitusajal muuta, eriti globaalselt hajutatud rakendustes. Konfiguratsiooni juhuslik muutmine ühes piirkonnas võib mõjutada kogu süsteemi.
const globalSettings = {
defaultLanguage: "en",
currency: "USD",
timeZone: "UTC"
};
const immutableHandler = {
set: function(target, property, value) {
throw new Error(`Ei saa muuta kirjutuskaitstud omadust: ${property}`);
}
};
const immutableSettings = new Proxy(globalSettings, immutableHandler);
console.log(immutableSettings.defaultLanguage); // väljastab 'en'
// Väärtuse muutmine viskab vea
// immutableSettings.defaultLanguage = "fr"; // viskab Error: Ei saa muuta kirjutuskaitstud omadust: defaultLanguage
4. Virtuaalne Proxy
Virtuaalne Proxy kontrollib juurdepääsu ressursile, mille loomine või hankimine võib olla kulukas. See võib ressursi loomist edasi lükata, kuni seda tegelikult vaja on.
Näide: Pildi laisk laadimine (lazy loading).
const image = {
display: function() {
console.log('Pildi kuvamine');
}
};
const virtualProxy = {
get: function(target, property) {
if (property === 'display') {
console.log('Pildi loomine...');
const realImage = {
display: function() {
console.log('Päris pildi kuvamine');
}
};
target.display = realImage.display;
return realImage.display;
}
return target[property];
}
};
const proxy = new Proxy(image, virtualProxy);
// Pilti ei looda enne, kui kutsutakse display meetodit.
proxy.display(); // Logib: Pildi loomine..., seejärel Päris pildi kuvamine
Päris pildiobjekt luuakse alles siis, kui kutsutakse meetodit display, vältides nii tarbetut ressursikulu.
Globaalne näide: Kujutage ette globaalset e-kaubanduse veebisaiti, mis pakub tootepilte. Virtuaalse Proxy abil saab pilte laadida alles siis, kui need on kasutajale nähtavad, optimeerides ribalaiuse kasutust ja parandades lehe laadimisaegu, eriti kasutajate jaoks, kellel on aeglane internetiühendus erinevates piirkondades.
const product = {
loadImage: function() {
console.log("Kõrge resolutsiooniga pildi laadimine...");
// Simuleerib suure pildi laadimist
setTimeout(() => {
console.log("Pilt laetud");
this.displayImage();
}, 2000);
},
displayImage: function() {
console.log("Pildi kuvamine");
}
};
const lazyLoadProxy = {
get: function(target, property) {
if (property === "displayImage") {
// Kohese laadimise asemel lükka laadimine edasi
console.log("Pildi kuvamise taotlus vastu võetud. Laadimine...");
target.loadImage();
return function() { /* Tahtlikult tühi */ }; // Tagasta tühi funktsioon kohese täitmise vältimiseks
}
return target[property];
}
};
const proxiedProduct = new Proxy(product, lazyLoadProxy);
// displayImage kutse käivitab laisa laadimise protsessi
proxiedProduct.displayImage();
5. Tühistatav Proxy
Tühistatav Proxy võimaldab teil proxy igal ajal tühistada, muutes selle kasutuskõlbmatuks. See on kasulik turvatundlikes stsenaariumides, kus peate kontrollima juurdepääsu objektile.
Näide: Ajutise juurdepääsu andmine ressursile.
const target = {
secret: 'See on saladus'
};
const handler = {
get: function(target, property) {
console.log('Juurdepääs salajasele omadusele');
return target[property];
}
};
const { proxy, revoke } = Proxy.revocable(target, handler);
console.log(proxy.secret); // Logib: Juurdepääs salajasele omadusele, seejärel See on saladus
revoke();
try {
console.log(proxy.secret); // Visatakse TypeError
} catch (error) {
console.error(error.message); // Logib: Ei saa sooritada 'get' operatsiooni tühistatud proxy'l
}
Meetod Proxy.revocable() loob tühistatava proxy. Funktsiooni revoke() kutsumine muudab proxy kasutuskõlbmatuks, takistades edasist juurdepääsu sihtmärkobjektile.
Globaalne näide: Globaalselt hajutatud süsteemis võite kasutada tühistatavat proxyt, et anda ajutine juurdepääs tundlikele andmetele teenusele, mis töötab kindlas piirkonnas. Teatud aja möödudes saab proxy tühistada, et vältida volitamata juurdepääsu.
const sensitiveData = {
apiKey: "SUPER_SECRET_KEY"
};
const handler = {
get: function(target, property) {
console.log("Juurdepääs tundlikele andmetele");
return target[property];
}
};
const { proxy: dataProxy, revoke: revokeAccess } = Proxy.revocable(sensitiveData, handler);
// Luba juurdepääs 5 sekundiks
setTimeout(() => {
revokeAccess();
console.log("Juurdepääs tühistatud");
}, 5000);
// Proovi andmetele juurde pääseda
console.log(dataProxy.apiKey); // Logib API võtme
// 5 sekundi pärast viskab see vea
setTimeout(() => {
try {
console.log(dataProxy.apiKey); // Visatakse: TypeError: Ei saa sooritada 'get' operatsiooni tühistatud proxy'l
} catch (error) {
console.error(error);
}
}, 6000);
6. Tüübiteisendusega Proxy
Tüübiteisendusega Proxy kuulab pealt omadusele juurdepääsu, et automaatselt teisendada tagastatud väärtus kindlasse tüüpi. See võib olla kasulik töötades andmetega erinevatest allikatest, millel võivad olla ebajärjekindlad tüübid.
Näide: Sõneväärtuste teisendamine numbriteks.
const data = {
price: '10.99',
quantity: '5'
};
const typeConverter = {
get: function(target, property) {
const value = target[property];
if (typeof value === 'string' && !isNaN(Number(value))) {
return Number(value);
}
return value;
}
};
const proxy = new Proxy(data, typeConverter);
console.log(proxy.price + 1); // Logib: 11.99 (number)
console.log(proxy.quantity * 2); // Logib: 10 (number)
Püüdur get kontrollib, kas omaduse väärtus on sõne, mida saab teisendada numbriks. Kui jah, siis teisendab see väärtuse numbriks enne selle tagastamist.
Globaalne näide: Tegeledes andmetega, mis pärinevad erinevate vorminduskonventsioonidega API-dest (nt erinevad kuupäevavormingud või valuutasümbolid), saab tüübiteisendusega Proxy tagada andmete järjepidevuse kogu rakenduses, olenemata allikast. Näiteks erinevate kuupäevavormingute käsitlemine ja nende kõigi teisendamine ISO 8601 vormingusse.
const apiData = {
dateUS: "12/31/2023",
dateEU: "31/12/2023"
};
const dateFormatConverter = {
get: function(target, property) {
let value = target[property];
if (property.startsWith("date")) {
// Püüe teisendada nii USA kui ka ELi kuupäevavormingud ISO 8601 vormingusse
if (property === "dateUS") {
const [month, day, year] = value.split("/");
value = `${year}-${month}-${day}`;
} else if (property === "dateEU") {
const [day, month, year] = value.split("/");
value = `${year}-${month}-${day}`;
}
return value;
}
return value;
}
};
const proxiedApiData = new Proxy(apiData, dateFormatConverter);
console.log(proxiedApiData.dateUS); // Väljastab: 2023-12-31
console.log(proxiedApiData.dateEU); // Väljastab: 2023-12-31
Parimad praktikad Proxyde kasutamisel
- Kasutage Proxysid läbimõeldult: Proxyd võivad teie koodile keerukust lisada. Kasutage neid ainult siis, kui need pakuvad olulist kasu, näiteks paremat valideerimist, logimist või kontrolli objekti käitumise üle.
- Arvestage jõudlusega: Proxy püüdurid võivad tekitada lisakoormust. Profileerige oma koodi, et tagada, et Proxyd ei mõjutaks negatiivselt jõudlust, eriti jõudluskriitilistes osades.
- Käsitlege vigu sujuvalt: Veenduge, et teie püüdurimeetodid käsitleksid vigu asjakohaselt, pakkudes vajadusel informatiivseid veateateid.
- Kasutage Reflect API-t:
ReflectAPI pakub meetodeid, mis peegeldavad objekti operatsioonide vaikekäitumist. KasutageReflectmeetodeid oma püüdurimeetodites, et delegeerida algsele käitumisele, kui see on asjakohane. See tagab, et teie püüdurid ei riku olemasolevat funktsionaalsust. - Dokumenteerige oma Proxyd: Dokumenteerige selgelt oma Proxyde eesmärk ja käitumine, sealhulgas kasutatavad püüdurid ja rakendatavad piirangud. See aitab teistel arendajatel teie koodi mõista ja hooldada.
Kokkuvõte
JavaScripti Proxyd on võimas tööriist täiustatud objektide manipuleerimiseks ja pealtkuulamiseks. Mõistes ja rakendades erinevaid Proxy mustreid, saate parandada koodi kvaliteeti, turvalisust ja hooldatavust. Alates kasutaja sisendi valideerimisest kuni tundlikele ressurssidele juurdepääsu kontrollimiseni pakuvad Proxyd paindlikku ja laiendatavat mehhanismi objekti käitumise kohandamiseks. Proxyde võimalusi uurides pidage meeles neid läbimõeldult kasutada ja oma koodi põhjalikult dokumenteerida.
Esitatud näited demonstreerivad, kuidas kasutada JavaScripti Proxysid reaalsete probleemide lahendamiseks globaalses kontekstis. Neid mustreid mõistes ja rakendades saate luua robustsemaid, turvalisemaid ja hooldatavamaid rakendusi, mis vastavad mitmekesise kasutajaskonna vajadustele. Pidage alati meeles oma koodi globaalseid mõjusid ja kohandage oma lahendusi vastavalt erinevate piirkondade ja kultuuride spetsiifilistele nõuetele.