Avastage JavaScript Proxy mustreid objektikäitumise muutmiseks. Õppige valideerimist, virtualiseerimist, jälgimist ja teisi täiustatud tehnikaid koodinäidetega.
JavaScript Proxy mustrid: objektikäitumise muutmise valdamine
JavaScripti Proxy-objekt pakub võimsat mehhanismi objektide põhioperatsioonide pealtkuulamiseks ja kohandamiseks. See võimekus avab uksed laiale valikule disainimustritele ja täiustatud tehnikatele objektikäitumise kontrollimiseks. See põhjalik juhend uurib erinevaid Proxy mustreid, illustreerides nende kasutust praktiliste koodinäidetega.
Mis on JavaScripti Proxy?
Proxy-objekt ümbritseb teise objekti (sihtobjekti) ja kuulab pealt selle operatsioone. Need operatsioonid, mida tuntakse kui püüniseid (traps), hõlmavad omadustele juurdepääsu, väärtuste määramist, loendamist ja funktsioonide väljakutsumist. Proxy võimaldab teil määratleda kohandatud loogikat, mida käivitatakse enne, pärast või nende operatsioonide asemel. Proxy põhikontseptsioon hõlmab "metaprogrammeerimist", mis võimaldab teil manipuleerida JavaScripti keele enda käitumisega.
Proxy loomise põhisüntaks on:
const proxy = new Proxy(target, handler);
- target: Algne objekt, mida soovite proksida.
- handler: Objekt, mis sisaldab meetodeid (püüniseid), mis määratlevad, kuidas Proxy sihtobjekti operatsioone pealt kuulab.
Levinud Proxy püünised
Handler-objekt võib määratleda mitmeid püüniseid. Siin on mõned kõige sagedamini kasutatavad:
- get(target, property, receiver): Kuulab pealt omadusele juurdepääsu (nt
obj.property
). - set(target, property, value, receiver): Kuulab pealt omaduse väärtustamist (nt
obj.property = value
). - has(target, property): Kuulab pealt
in
operaatorit (nt'property' in obj
). - deleteProperty(target, property): Kuulab pealt
delete
operaatorit (ntdelete obj.property
). - apply(target, thisArg, argumentsList): Kuulab pealt funktsioonikutseid (kui sihtobjekt on funktsioon).
- construct(target, argumentsList, newTarget): Kuulab pealt
new
operaatorit (kui sihtobjekt on konstruktorfunktsioon). - getPrototypeOf(target): Kuulab pealt kutseid meetodile
Object.getPrototypeOf()
. - setPrototypeOf(target, prototype): Kuulab pealt kutseid meetodile
Object.setPrototypeOf()
. - isExtensible(target): Kuulab pealt kutseid meetodile
Object.isExtensible()
. - preventExtensions(target): Kuulab pealt kutseid meetodile
Object.preventExtensions()
. - getOwnPropertyDescriptor(target, property): Kuulab pealt kutseid meetodile
Object.getOwnPropertyDescriptor()
. - defineProperty(target, property, descriptor): Kuulab pealt kutseid meetodile
Object.defineProperty()
. - ownKeys(target): Kuulab pealt kutseid meetoditele
Object.getOwnPropertyNames()
jaObject.getOwnPropertySymbols()
.
Proxy mustrid ja kasutusjuhud
Uurime mõningaid levinud Proxy mustreid ja seda, kuidas neid saab rakendada reaalsetes stsenaariumides:
1. Valideerimine
Valideerimismuster kasutab Proxy't, et jõustada piiranguid omaduste väärtustamisel. See on kasulik andmete terviklikkuse tagamiseks.
const validator = {
set: function(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('Age is not an integer');
}
if (value < 0) {
throw new RangeError('Age must be a non-negative integer');
}
}
// Vaikekäitumine väärtuse salvestamiseks
obj[prop] = value;
// Annab teada õnnestumisest
return true;
}
};
let person = {};
let proxy = new Proxy(person, validator);
proxy.age = 25; // Kehtiv
console.log(proxy.age); // Väljund: 25
try {
proxy.age = 'young'; // Visatakse TypeError
} catch (e) {
console.log(e); // Väljund: TypeError: Age is not an integer
}
try {
proxy.age = -10; // Visatakse RangeError
} catch (e) {
console.log(e); // Väljund: RangeError: Age must be a non-negative integer
}
Näide: Kujutage ette e-kaubanduse platvormi, kus kasutajaandmed vajavad valideerimist. Proxy saab jõustada reegleid vanuse, e-posti vormingu, parooli tugevuse ja muude väljade kohta, vältides kehtetute andmete salvestamist.
2. Virtualiseerimine (laisk laadimine)
Virtualiseerimine, tuntud ka kui laisk laadimine (lazy loading), lükkab kulukate ressursside laadimise edasi, kuni neid tegelikult vaja läheb. Proxy võib toimida tõelise objekti kohatäitjana, laadides selle alles siis, kui omadusele juurde pääsetakse.
const expensiveData = {
load: function() {
console.log('Kalli ressursi laadimine...');
// Simuleerib aeganõudvat operatsiooni (nt andmebaasist pärimine)
return new Promise(resolve => {
setTimeout(() => {
resolve({
data: 'This is the expensive data'
});
}, 2000);
});
}
};
const lazyLoadHandler = {
get: function(target, prop) {
if (prop === 'data') {
console.log('Andmetele juurdepääs, vajadusel laadimine...');
return target.load().then(result => {
target.data = result.data; // Salvesta laetud andmed
return result.data;
});
} else {
return target[prop];
}
}
};
const lazyData = new Proxy(expensiveData, lazyLoadHandler);
console.log('Esmakordne juurdepääs...');
lazyData.data.then(data => {
console.log('Data:', data); // Väljund: Data: This is the expensive data
});
console.log('Järgnev juurdepääs...');
lazyData.data.then(data => {
console.log('Data:', data); // Väljund: Data: This is the expensive data (laetud vahemälust)
});
Näide: Kujutage ette suurt sotsiaalmeedia platvormi kasutajaprofiilidega, mis sisaldavad arvukalt detaile ja seotud meediat. Kogu profiiliinfo kohene laadimine võib olla ebaefektiivne. Virtualiseerimine Proxy abil võimaldab esmalt laadida põhilise profiiliinfo ja seejärel laadida täiendavaid detaile või meediasisu alles siis, kui kasutaja nendesse jaotistesse navigeerib.
3. Logimine ja jälgimine
Proxy'sid saab kasutada omadustele juurdepääsu ja muudatuste jälgimiseks. See on väärtuslik silumisel, auditeerimisel ja jõudluse jälgimisel.
const logHandler = {
get: function(target, prop, receiver) {
console.log(`GET ${prop}`);
return Reflect.get(target, prop, receiver);
},
set: function(target, prop, value) {
console.log(`SET ${prop} to ${value}`);
target[prop] = value;
return true;
}
};
let obj = { name: 'Alice' };
let proxy = new Proxy(obj, logHandler);
console.log(proxy.name); // Väljund: GET name, Alice
proxy.age = 30; // Väljund: SET age to 30
Näide: Koostööl põhinevas dokumenditöötlusrakenduses saab Proxy jälgida iga muudatust, mis dokumendi sisule tehakse. See võimaldab luua auditeerimisjälje, võimaldada tagasivõtmise/uuestitegemise funktsionaalsust ja pakkuda ülevaadet kasutajate panusest.
4. Kirjutuskaitstud vaated
Proxy'd saavad luua objektidest kirjutuskaitstud vaateid, vältides juhuslikke muudatusi. See on kasulik tundlike andmete kaitsmiseks.
const readOnlyHandler = {
set: function(target, prop, value) {
console.error(`Cannot set property ${prop}: object is read-only`);
return false; // Annab teada, et väärtustamise operatsioon ebaõnnestus
},
deleteProperty: function(target, prop) {
console.error(`Cannot delete property ${prop}: object is read-only`);
return false; // Annab teada, et kustutamise operatsioon ebaõnnestus
}
};
let data = { name: 'Bob', age: 40 };
let readOnlyData = new Proxy(data, readOnlyHandler);
try {
readOnlyData.age = 41; // Visatakse viga
} catch (e) {
console.log(e); // Viga ei visata, kuna 'set' püünis tagastab false.
}
try {
delete readOnlyData.name; // Visatakse viga
} catch (e) {
console.log(e); // Viga ei visata, kuna 'deleteProperty' püünis tagastab false.
}
console.log(data.age); // Väljund: 40 (muutmata)
Näide: Kujutage ette finantssüsteemi, kus mõnedel kasutajatel on ainult lugemisõigus kontoteabele. Proxy't saab kasutada, et takistada neil kasutajatel kontojääkide või muude kriitiliste andmete muutmist.
5. Vaikeväärtused
Proxy saab pakkuda vaikeväärtusi puuduvate omaduste jaoks. See lihtsustab koodi ja väldib null/undefined kontrolle.
const defaultValuesHandler = {
get: function(target, prop, receiver) {
if (!(prop in target)) {
console.log(`Property ${prop} not found, returning default value.`);
return 'Default Value'; // Või mõni muu sobiv vaikeväärtus
}
return Reflect.get(target, prop, receiver);
}
};
let config = { apiUrl: 'https://api.example.com' };
let configWithDefaults = new Proxy(config, defaultValuesHandler);
console.log(configWithDefaults.apiUrl); // Väljund: https://api.example.com
console.log(configWithDefaults.timeout); // Väljund: Property timeout not found, returning default value. Default Value
Näide: Konfiguratsioonihaldussüsteemis saab Proxy pakkuda vaikeväärtusi puuduvate seadete jaoks. Näiteks, kui konfiguratsioonifail ei määra andmebaasiühenduse ajalõppu, saab Proxy tagastada eelmääratletud vaikeväärtuse.
6. Metaandmed ja annotatsioonid
Proxy'd saavad objektidele lisada metaandmeid või annotatsioone, pakkudes lisateavet ilma algset objekti muutmata.
const metadataHandler = {
get: function(target, prop, receiver) {
if (prop === '__metadata__') {
return { description: 'This is metadata for the object' };
}
return Reflect.get(target, prop, receiver);
}
};
let article = { title: 'Introduction to Proxies', content: '...' };
let articleWithMetadata = new Proxy(article, metadataHandler);
console.log(articleWithMetadata.title); // Väljund: Introduction to Proxies
console.log(articleWithMetadata.__metadata__.description); // Väljund: This is metadata for the object
Näide: Sisuhaldussüsteemis saab Proxy lisada artiklitele metaandmeid, nagu autoriinfo, avaldamiskuupäev ja märksõnad. Neid metaandmeid saab kasutada sisu otsimiseks, filtreerimiseks ja kategoriseerimiseks.
7. Funktsioonide pealtkuulamine
Proxy'd saavad pealt kuulata funktsioonikutseid, võimaldades teil lisada logimist, valideerimist või muud eel- või järeltöötlusloogikat.
const functionInterceptor = {
apply: function(target, thisArg, argumentsList) {
console.log('Calling function with arguments:', argumentsList);
const result = target.apply(thisArg, argumentsList);
console.log('Function returned:', result);
return result;
}
};
function add(a, b) {
return a + b;
}
let proxiedAdd = new Proxy(add, functionInterceptor);
let sum = proxiedAdd(5, 3); // Väljund: Calling function with arguments: [5, 3], Function returned: 8
console.log(sum); // Väljund: 8
Näide: Pangandusrakenduses saab Proxy pealt kuulata tehingufunktsioonide kutseid, logides iga tehingu ja teostades pettuste tuvastamise kontrolle enne tehingu täideviimist.
8. Konstruktorite pealtkuulamine
Proxy'd saavad pealt kuulata konstruktorikutseid, võimaldades teil kohandada objektide loomist.
const constructorInterceptor = {
construct: function(target, argumentsList, newTarget) {
console.log('Creating a new instance of', target.name, 'with arguments:', argumentsList);
const obj = new target(...argumentsList);
console.log('New instance created:', obj);
return obj;
}
};
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
let ProxiedPerson = new Proxy(Person, constructorInterceptor);
let person = new ProxiedPerson('Alice', 28); // Väljund: Creating a new instance of Person with arguments: ['Alice', 28], New instance created: Person { name: 'Alice', age: 28 }
console.log(person);
Näide: Mänguarenduse raamistikus saab Proxy pealt kuulata mänguobjektide loomist, määrates neile automaatselt unikaalsed ID-d, lisades vaikimisi komponente ja registreerides need mängumootoris.
Täiendavad kaalutlused
- Jõudlus: Kuigi Proxy'd pakuvad paindlikkust, võivad nad lisada jõudluskoormust. On oluline oma koodi testida ja profileerida, et tagada, et Proxy'de kasutamise eelised kaaluvad üles jõudluskulud, eriti jõudluskriitilistes rakendustes.
- Ühilduvus: Proxy'd on JavaScriptis suhteliselt uus lisandus, seega vanemad brauserid ei pruugi neid toetada. Kasutage funktsioonide tuvastamist või polüfille, et tagada ühilduvus vanemate keskkondadega.
- Tühistatavad Proxy'd: Meetod
Proxy.revocable()
loob Proxy, mida saab tühistada. Proxy tühistamine takistab edasiste operatsioonide pealtkuulamist. See võib olla kasulik turvalisuse või ressursside haldamise eesmärgil. - Reflect API: Reflect API pakub meetodeid Proxy püüniste vaikekäitumise teostamiseks.
Reflect
'i kasutamine tagab, et teie Proxy-kood käitub kooskõlas keele spetsifikatsiooniga.
Kokkuvõte
JavaScripti Proxy'd pakuvad võimsat ja mitmekülgset mehhanismi objektikäitumise kohandamiseks. Erinevate Proxy mustrite valdamisega saate kirjutada robustsemat, hooldatavamat ja tõhusamat koodi. Olgu tegemist valideerimise, virtualiseerimise, jälgimise või muude täiustatud tehnikate rakendamisega, pakuvad Proxy'd paindlikku lahendust objektidele juurdepääsu ja nendega manipuleerimise kontrollimiseks. Arvestage alati jõudlusmõjudega ja tagage ühilduvus sihtkeskkondadega. Proxy'd on kaasaegse JavaScripti arendaja arsenalis võtmetähtsusega tööriist, mis võimaldab võimsaid metaprogrammeerimise tehnikaid.
Edasiseks uurimiseks
- Mozilla Developer Network (MDN): JavaScript Proxy
- Exploring JavaScript Proxies: Smashing Magazine'i artikkel