జావాస్క్రిప్ట్ ప్రాక్సీ APIని నైపుణ్యం సాధించడానికి ప్రపంచ డెవలపర్ల కోసం ఒక సమగ్ర మార్గదర్శి. ఆబ్జెక్ట్ కార్యకలాపాలను అడ్డగించడం మరియు అనుకూలీకరించడం, ఆచరణాత్మక ఉదాహరణలు, వినియోగ సందర్భాలు మరియు పనితీరు చిట్కాలతో నేర్చుకోండి.
జావాస్క్రిప్ట్ ప్రాక్సీ API: ఆబ్జెక్ట్ ప్రవర్తన సవరణపై ఒక లోతైన విశ్లేషణ
ఆధునిక జావాస్క్రిప్ట్ యొక్క అభివృద్ధి చెందుతున్న ప్రపంచంలో, డెవలపర్లు డేటాను నిర్వహించడానికి మరియు దానితో పరస్పరం వ్యవహరించడానికి మరింత శక్తివంతమైన మరియు సొగసైన మార్గాలను నిరంతరం అన్వేషిస్తున్నారు. క్లాసులు, మాడ్యూల్స్, మరియు async/await వంటి ఫీచర్లు మనం కోడ్ రాసే విధానాన్ని విప్లవాత్మకంగా మార్చినప్పటికీ, ECMAScript 2015 (ES6) లో పరిచయం చేయబడిన ఒక శక్తివంతమైన మెటాప్రోగ్రామింగ్ ఫీచర్ ఉంది, అది తరచుగా తక్కువగా ఉపయోగించబడుతుంది: అదే ప్రాక్సీ API.
మెటాప్రోగ్రామింగ్ అనే పదం భయపెట్టేలా అనిపించవచ్చు, కానీ ఇది కేవలం ఇతర కోడ్పై పనిచేసే కోడ్ను రాయడం అనే భావన. ప్రాక్సీ API దీనికి జావాస్క్రిప్ట్ యొక్క ప్రాథమిక సాధనం, ఇది మరొక ఆబ్జెక్ట్ కోసం 'ప్రాక్సీ'ని సృష్టించడానికి మిమ్మల్ని అనుమతిస్తుంది, ఇది ఆ ఆబ్జెక్ట్ కోసం ప్రాథమిక కార్యకలాపాలను అడ్డగించి, పునర్నిర్వచించగలదు. ఇది ఒక ఆబ్జెక్ట్ ముందు ఒక అనుకూలీకరించదగిన ద్వారపాలకుడిని ఉంచడం లాంటిది, అది ఎలా యాక్సెస్ చేయబడుతుంది మరియు సవరించబడుతుంది అనే దానిపై మీకు పూర్తి నియంత్రణను ఇస్తుంది.
ఈ సమగ్ర గైడ్ ప్రాక్సీ APIని సులభంగా వివరిస్తుంది. మేము దాని ప్రధాన భావనలను అన్వేషిస్తాము, ఆచరణాత్మక ఉదాహరణలతో దాని వివిధ సామర్థ్యాలను విడదీసి చర్చిస్తాము, మరియు అధునాతన వినియోగ సందర్భాలు మరియు పనితీరు పరిగణనలను చర్చిస్తాము. చివరికి, ఆధునిక ఫ్రేమ్వర్క్లలో ప్రాక్సీలు ఎందుకు మూలస్తంభంగా ఉన్నాయో మరియు శుభ్రమైన, మరింత శక్తివంతమైన, మరియు మరింత నిర్వహించదగిన కోడ్ను రాయడానికి మీరు వాటిని ఎలా ఉపయోగించుకోవచ్చో మీరు అర్థం చేసుకుంటారు.
ప్రధాన భావనలను అర్థం చేసుకోవడం: టార్గెట్, హ్యాండ్లర్, మరియు ట్రాప్లు
ప్రాక్సీ API మూడు ప్రాథమిక భాగాలపై నిర్మించబడింది. వాటి పాత్రలను అర్థం చేసుకోవడం ప్రాక్సీలను నైపుణ్యం సాధించడానికి కీలకం.
- టార్గెట్ (Target): ఇది మీరు చుట్టాలనుకుంటున్న అసలు ఆబ్జెక్ట్. ఇది శ్రేణులు, ఫంక్షన్లు లేదా మరొక ప్రాక్సీతో సహా ఏ రకమైన ఆబ్జెక్ట్ అయినా కావచ్చు. ప్రాక్సీ ఈ టార్గెట్ను వర్చువలైజ్ చేస్తుంది, మరియు అన్ని కార్యకలాపాలు చివరికి (అవసరంగా కాకపోయినా) దానికి ఫార్వార్డ్ చేయబడతాయి.
- హ్యాండ్లర్ (Handler): ఇది ప్రాక్సీ యొక్క తర్కాన్ని కలిగి ఉన్న ఒక ఆబ్జెక్ట్. ఇది ఒక ప్లేస్హోల్డర్ ఆబ్జెక్ట్, దీని లక్షణాలు ఫంక్షన్లు, వీటిని 'ట్రాప్లు' అని పిలుస్తారు. ప్రాక్సీపై ఒక ఆపరేషన్ జరిగినప్పుడు, అది హ్యాండ్లర్పై సంబంధిత ట్రాప్ కోసం చూస్తుంది.
- ట్రాప్లు (Traps): ఇవి హ్యాండ్లర్పై ప్రాపర్టీ యాక్సెస్ను అందించే పద్ధతులు. ప్రతి ట్రాప్ ఒక ప్రాథమిక ఆబ్జెక్ట్ ఆపరేషన్కు అనుగుణంగా ఉంటుంది. ఉదాహరణకు,
get
ట్రాప్ ప్రాపర్టీ చదవడాన్ని అడ్డగిస్తుంది, మరియుset
ట్రాప్ ప్రాపర్టీ రాయడాన్ని అడ్డగిస్తుంది. ఒక ట్రాప్ హ్యాండ్లర్పై నిర్వచించబడకపోతే, ఆపరేషన్ ప్రాక్సీ లేనట్లుగా టార్గెట్కు ఫార్వార్డ్ చేయబడుతుంది.
ఒక ప్రాక్సీని సృష్టించడానికి సింటాక్స్ సూటిగా ఉంటుంది:
const proxy = new Proxy(target, handler);
ఒక చాలా ప్రాథమిక ఉదాహరణను చూద్దాం. మేము ఒక ఖాళీ హ్యాండ్లర్ను ఉపయోగించి అన్ని కార్యకలాపాలను టార్గెట్ ఆబ్జెక్ట్కు పంపే ఒక ప్రాక్సీని సృష్టిస్తాము.
// అసలు ఆబ్జెక్ట్
const target = {
message: "Hello, World!"
};
// ఒక ఖాళీ హ్యాండ్లర్. అన్ని కార్యకలాపాలు టార్గెట్కు ఫార్వార్డ్ చేయబడతాయి.
const handler = {};
// ప్రాక్సీ ఆబ్జెక్ట్
const proxy = new Proxy(target, handler);
// ప్రాక్సీపై ఒక ప్రాపర్టీని యాక్సెస్ చేయడం
console.log(proxy.message); // అవుట్పుట్: Hello, World!
// ఆపరేషన్ టార్గెట్కు ఫార్వార్డ్ చేయబడింది
console.log(target.message); // అవుట్పుట్: Hello, World!
// ప్రాక్సీ ద్వారా ఒక ప్రాపర్టీని సవరించడం
proxy.anotherMessage = "Hello, Proxy!";
console.log(proxy.anotherMessage); // అవుట్పుట్: Hello, Proxy!
console.log(target.anotherMessage); // అవుట్పుట్: Hello, Proxy!
ఈ ఉదాహరణలో, ప్రాక్సీ అసలు ఆబ్జెక్ట్ లాగానే ప్రవర్తిస్తుంది. మనం హ్యాండ్లర్లో ట్రాప్లను నిర్వచించడం ప్రారంభించినప్పుడు అసలు శక్తి వస్తుంది.
ప్రాక్సీ యొక్క నిర్మాణం: సాధారణ ట్రాప్లను అన్వేషించడం
హ్యాండ్లర్ ఆబ్జెక్ట్ 13 వేర్వేరు ట్రాప్లను కలిగి ఉంటుంది, ప్రతి ఒక్కటి జావాస్క్రిప్ట్ ఆబ్జెక్ట్ల యొక్క ఒక ప్రాథమిక అంతర్గత పద్ధతికి అనుగుణంగా ఉంటుంది. అత్యంత సాధారణ మరియు ఉపయోగకరమైన వాటిని అన్వేషిద్దాం.
ప్రాపర్టీ యాక్సెస్ ట్రాప్లు
1. `get(target, property, receiver)`
ఇది వాదించదగినంతగా అత్యంత ఎక్కువగా ఉపయోగించబడే ట్రాప్. ప్రాక్సీ యొక్క ఒక ప్రాపర్టీ చదవబడినప్పుడు ఇది ప్రేరేపించబడుతుంది.
target
: అసలు ఆబ్జెక్ట్.property
: యాక్సెస్ చేయబడుతున్న ప్రాపర్టీ పేరు.receiver
: ప్రాక్సీ స్వయంగా, లేదా దాని నుండి వారసత్వంగా పొందిన ఒక ఆబ్జెక్ట్.
ఉదాహరణ: ఉనికిలో లేని ప్రాపర్టీల కోసం డిఫాల్ట్ విలువలు.
const user = {
firstName: 'John',
lastName: 'Doe',
age: 30
};
const userHandler = {
get(target, property) {
// ప్రాపర్టీ టార్గెట్పై ఉంటే, దానిని తిరిగి ఇవ్వండి.
// లేకపోతే, ఒక డిఫాల్ట్ సందేశాన్ని తిరిగి ఇవ్వండి.
return property in target ? target[property] : `ప్రాపర్టీ '${property}' ఉనికిలో లేదు.`;
}
};
const userProxy = new Proxy(user, userHandler);
console.log(userProxy.firstName); // అవుట్పుట్: John
console.log(userProxy.age); // అవుట్పుట్: 30
console.log(userProxy.country); // అవుట్పుట్: ప్రాపర్టీ 'country' ఉనికిలో లేదు.
2. `set(target, property, value, receiver)`
ప్రాక్సీ యొక్క ఒక ప్రాపర్టీకి ఒక విలువను కేటాయించినప్పుడు set
ట్రాప్ పిలువబడుతుంది. ఇది ధృవీకరణ, లాగింగ్, లేదా రీడ్-ఓన్లీ ఆబ్జెక్ట్లను సృష్టించడానికి ఖచ్చితంగా సరిపోతుంది.
value
: ప్రాపర్టీకి కేటాయించబడుతున్న కొత్త విలువ.- ట్రాప్ ఒక బూలియన్ను తిరిగి ఇవ్వాలి:
true
అయితే కేటాయింపు విజయవంతమైంది, మరియుfalse
అయితే (ఇది స్ట్రిక్ట్ మోడ్లోTypeError
ను త్రో చేస్తుంది).
ఉదాహరణ: డేటా ధృవీకరణ.
const person = {
name: 'Jane Doe',
age: 25
};
const validationHandler = {
set(target, property, value) {
if (property === 'age') {
if (typeof value !== 'number' || !Number.isInteger(value)) {
throw new TypeError('వయస్సు ఒక పూర్ణాంకం అయి ఉండాలి.');
}
if (value <= 0) {
throw new RangeError('వయస్సు ఒక ధన సంఖ్య అయి ఉండాలి.');
}
}
// ధృవీకరణ ఉత్తీర్ణత సాధిస్తే, టార్గెట్ ఆబ్జెక్ట్పై విలువను సెట్ చేయండి.
target[property] = value;
// విజయాన్ని సూచించండి.
return true;
}
};
const personProxy = new Proxy(person, validationHandler);
personProxy.age = 30; // ఇది చెల్లుబాటు అవుతుంది
console.log(personProxy.age); // అవుట్పుట్: 30
try {
personProxy.age = 'thirty'; // TypeError త్రో చేస్తుంది
} catch (e) {
console.error(e.message); // అవుట్పుట్: వయస్సు ఒక పూర్ణాంకం అయి ఉండాలి.
}
try {
personProxy.age = -5; // RangeError త్రో చేస్తుంది
} catch (e) {
console.error(e.message); // అవుట్పుట్: వయస్సు ఒక ధన సంఖ్య అయి ఉండాలి.
}
3. `has(target, property)`
ఈ ట్రాప్ in
ఆపరేటర్ను అడ్డగిస్తుంది. ఇది ఒక ఆబ్జెక్ట్పై ఏ ప్రాపర్టీలు ఉన్నట్లుగా కనిపించాలో నియంత్రించడానికి మిమ్మల్ని అనుమతిస్తుంది.
ఉదాహరణ: 'ప్రైవేట్' ప్రాపర్టీలను దాచడం.
జావాస్క్రిప్ట్లో, ప్రైవేట్ ప్రాపర్టీలను అండర్స్కోర్ (_) తో ముందుగా చేర్చడం ఒక సాధారణ సంప్రదాయం. ఈ ప్రాపర్టీలను in
ఆపరేటర్ నుండి దాచడానికి మనం has
ట్రాప్ను ఉపయోగించవచ్చు.
const secretData = {
_apiKey: 'xyz123abc',
publicKey: 'pub456def',
id: 1
};
const hidingHandler = {
has(target, property) {
if (property.startsWith('_')) {
return false; // ఇది లేనట్లుగా నటించండి
}
return property in target;
}
};
const dataProxy = new Proxy(secretData, hidingHandler);
console.log('publicKey' in dataProxy); // అవుట్పుట్: true
console.log('_apiKey' in dataProxy); // అవుట్పుట్: false (టార్గెట్పై ఉన్నప్పటికీ)
console.log('id' in dataProxy); // అవుట్పుట్: true
గమనిక: ఇది కేవలం in
ఆపరేటర్ను మాత్రమే ప్రభావితం చేస్తుంది. మీరు సంబంధిత get
ట్రాప్ను కూడా అమలు చేస్తే తప్ప, dataProxy._apiKey
వంటి ప్రత్యక్ష యాక్సెస్ ఇప్పటికీ పనిచేస్తుంది.
4. `deleteProperty(target, property)`
delete
ఆపరేటర్ను ఉపయోగించి ఒక ప్రాపర్టీని తొలగించినప్పుడు ఈ ట్రాప్ అమలు చేయబడుతుంది. ముఖ్యమైన ప్రాపర్టీల తొలగింపును నిరోధించడానికి ఇది ఉపయోగపడుతుంది.
ట్రాప్ విజయవంతమైన తొలగింపు కోసం true
ను లేదా విఫలమైన తొలగింపు కోసం false
ను తిరిగి ఇవ్వాలి.
ఉదాహరణ: ప్రాపర్టీల తొలగింపును నిరోధించడం.
const immutableConfig = {
databaseUrl: 'prod.db.server',
port: 8080
};
const deletionGuardHandler = {
deleteProperty(target, property) {
if (property in target) {
console.warn(`రక్షిత ప్రాపర్టీని తొలగించడానికి ప్రయత్నించారు: '${property}'. ఆపరేషన్ తిరస్కరించబడింది.`);
return false;
}
return true; // ప్రాపర్టీ ఎలాగూ ఉనికిలో లేదు
}
};
const configProxy = new Proxy(immutableConfig, deletionGuardHandler);
delete configProxy.port;
// కన్సోల్ అవుట్పుట్: రక్షిత ప్రాపర్టీని తొలగించడానికి ప్రయత్నించారు: 'port'. ఆపరేషన్ తిరస్కరించబడింది.
console.log(configProxy.port); // అవుట్పుట్: 8080 (ఇది తొలగించబడలేదు)
ఆబ్జెక్ట్ ఎన్యూమరేషన్ మరియు డిస్క్రిప్షన్ ట్రాప్లు
5. `ownKeys(target)`
ఈ ట్రాప్ Object.keys()
, Object.getOwnPropertyNames()
, Object.getOwnPropertySymbols()
, మరియు Reflect.ownKeys()
వంటి ఆబ్జెక్ట్ యొక్క స్వంత ప్రాపర్టీల జాబితాను పొందే కార్యకలాపాల ద్వారా ప్రేరేపించబడుతుంది.
ఉదాహరణ: కీలను ఫిల్టర్ చేయడం.
వాటిని పూర్తిగా దాచడానికి మన మునుపటి 'ప్రైవేట్' ప్రాపర్టీ ఉదాహరణతో దీనిని కలుపుదాం.
const secretData = {
_apiKey: 'xyz123abc',
publicKey: 'pub456def',
id: 1
};
const keyHidingHandler = {
has(target, property) {
return !property.startsWith('_') && property in target;
},
ownKeys(target) {
return Reflect.ownKeys(target).filter(key => !key.startsWith('_'));
},
get(target, property, receiver) {
// ప్రత్యక్ష యాక్సెస్ను కూడా నిరోధించండి
if (property.startsWith('_')) {
return undefined;
}
return Reflect.get(target, property, receiver);
}
};
const fullProxy = new Proxy(secretData, keyHidingHandler);
console.log(Object.keys(fullProxy)); // అవుట్పుట్: ['publicKey', 'id']
console.log('publicKey' in fullProxy); // అవుట్పుట్: true
console.log('_apiKey' in fullProxy); // అవుట్పుట్: false
console.log(fullProxy._apiKey); // అవుట్పుట్: undefined
ఇక్కడ మనం Reflect
ను ఉపయోగిస్తున్నామని గమనించండి. Reflect
ఆబ్జెక్ట్ అడ్డగించగల జావాస్క్రిప్ట్ కార్యకలాపాల కోసం పద్ధతులను అందిస్తుంది, మరియు దాని పద్ధతులు ప్రాక్సీ ట్రాప్ల వలె అదే పేర్లు మరియు సంతకాలను కలిగి ఉంటాయి. డిఫాల్ట్ ప్రవర్తన సరిగ్గా నిర్వహించబడుతుందని నిర్ధారించుకుంటూ, అసలు ఆపరేషన్ను టార్గెట్కు ఫార్వార్డ్ చేయడానికి Reflect
ను ఉపయోగించడం ఒక ఉత్తమ పద్ధతి.
ఫంక్షన్ మరియు కన్స్ట్రక్టర్ ట్రాప్లు
ప్రాక్సీలు సాదా ఆబ్జెక్ట్లకు మాత్రమే పరిమితం కాదు. టార్గెట్ ఒక ఫంక్షన్ అయినప్పుడు, మీరు కాల్స్ మరియు కన్స్ట్రక్షన్లను అడ్డగించవచ్చు.
6. `apply(target, thisArg, argumentsList)`
ఒక ఫంక్షన్ యొక్క ప్రాక్సీని అమలు చేసినప్పుడు ఈ ట్రాప్ పిలువబడుతుంది. ఇది ఫంక్షన్ కాల్ను అడ్డగిస్తుంది.
target
: అసలు ఫంక్షన్.thisArg
: కాల్ కోసంthis
సందర్భం.argumentsList
: ఫంక్షన్కు పంపబడిన ఆర్గ్యుమెంట్ల జాబితా.
ఉదాహరణ: ఫంక్షన్ కాల్స్ మరియు వాటి ఆర్గ్యుమెంట్లను లాగింగ్ చేయడం.
function sum(a, b) {
return a + b;
}
const loggingHandler = {
apply(target, thisArg, argumentsList) {
console.log(`ఫంక్షన్ '${target.name}' ను ఆర్గ్యుమెంట్లతో పిలుస్తున్నాము: ${argumentsList}`);
// అసలు ఫంక్షన్ను సరైన సందర్భం మరియు ఆర్గ్యుమెంట్లతో అమలు చేయండి
const result = Reflect.apply(target, thisArg, argumentsList);
console.log(`ఫంక్షన్ '${target.name}' తిరిగి ఇచ్చింది: ${result}`);
return result;
}
};
const proxiedSum = new Proxy(sum, loggingHandler);
proxiedSum(5, 10);
// కన్సోల్ అవుట్పుట్:
// ఫంక్షన్ 'sum' ను ఆర్గ్యుమెంట్లతో పిలుస్తున్నాము: 5,10
// ఫంక్షన్ 'sum' తిరిగి ఇచ్చింది: 15
7. `construct(target, argumentsList, newTarget)`
ఈ ట్రాప్ ఒక క్లాస్ లేదా ఫంక్షన్ యొక్క ప్రాక్సీపై new
ఆపరేటర్ వాడకాన్ని అడ్డగిస్తుంది.
ఉదాహరణ: సింగిల్టన్ ప్యాటర్న్ అమలు.
class MyDatabaseConnection {
constructor(url) {
this.url = url;
console.log(`${this.url}కు కనెక్ట్ అవుతోంది...`);
}
}
let instance;
const singletonHandler = {
construct(target, argumentsList) {
if (!instance) {
console.log('కొత్త ఇన్స్టాన్స్ను సృష్టిస్తోంది.');
instance = Reflect.construct(target, argumentsList);
}
console.log('ఇప్పటికే ఉన్న ఇన్స్టాన్స్ను తిరిగి ఇస్తోంది.');
return instance;
}
};
const ProxiedConnection = new Proxy(MyDatabaseConnection, singletonHandler);
const conn1 = new ProxiedConnection('db://primary');
// కన్సోల్ అవుట్పుట్:
// కొత్త ఇన్స్టాన్స్ను సృష్టిస్తోంది.
// db://primaryకు కనెక్ట్ అవుతోంది...
// ఇప్పటికే ఉన్న ఇన్స్టాన్స్ను తిరిగి ఇస్తోంది.
const conn2 = new ProxiedConnection('db://secondary'); // URL విస్మరించబడుతుంది
// కన్సోల్ అవుట్పుట్:
// ఇప్పటికే ఉన్న ఇన్స్టాన్స్ను తిరిగి ఇస్తోంది.
console.log(conn1 === conn2); // అవుట్పుట్: true
console.log(conn1.url); // అవుట్పుట్: db://primary
console.log(conn2.url); // అవుట్పుట్: db://primary
ఆచరణాత్మక వినియోగ సందర్భాలు మరియు అధునాతన ప్యాటర్న్లు
ఇప్పుడు మనం వ్యక్తిగత ట్రాప్లను కవర్ చేసాము, వాస్తవ ప్రపంచ సమస్యలను పరిష్కరించడానికి వాటిని ఎలా కలపవచ్చో చూద్దాం.
1. API అబ్స్ట్రాక్షన్ మరియు డేటా ట్రాన్స్ఫర్మేషన్
APIలు తరచుగా మీ అప్లికేషన్ యొక్క సంప్రదాయాలకు సరిపోలని ఫార్మాట్లో డేటాను తిరిగి ఇస్తాయి (ఉదా., snake_case
vs. camelCase
). ఒక ప్రాక్సీ ఈ మార్పిడిని పారదర్శకంగా నిర్వహించగలదు.
function snakeToCamel(s) {
return s.replace(/(_\w)/g, (m) => m[1].toUpperCase());
}
// ఇది ఒక API నుండి మా ముడి డేటా అని ఊహించుకోండి
const apiResponse = {
user_id: 123,
first_name: 'Alice',
last_name: 'Wonderland',
account_status: 'active'
};
const camelCaseHandler = {
get(target, property) {
const camelCaseProperty = snakeToCamel(property);
// camelCase వెర్షన్ నేరుగా ఉందో లేదో తనిఖీ చేయండి
if (camelCaseProperty in target) {
return target[camelCaseProperty];
}
// అసలు ప్రాపర్టీ పేరుకు ఫాల్బ్యాక్
if (property in target) {
return target[property];
}
return undefined;
}
};
const userModel = new Proxy(apiResponse, camelCaseHandler);
// మనం ఇప్పుడు camelCase ఉపయోగించి ప్రాపర్టీలను యాక్సెస్ చేయవచ్చు, అవి snake_case గా నిల్వ చేయబడినప్పటికీ
console.log(userModel.userId); // అవుట్పుట్: 123
console.log(userModel.firstName); // అవుట్పుట్: Alice
console.log(userModel.accountStatus); // అవుట్పుట్: active
2. అబ్జర్వబుల్స్ మరియు డేటా బైండింగ్ (ఆధునిక ఫ్రేమ్వర్క్ల యొక్క కోర్)
ప్రాక్సీలు Vue 3 వంటి ఆధునిక ఫ్రేమ్వర్క్లలో రియాక్టివిటీ సిస్టమ్ల వెనుక ఇంజిన్. మీరు ఒక ప్రాక్సీ చేయబడిన స్టేట్ ఆబ్జెక్ట్పై ఒక ప్రాపర్టీని మార్చినప్పుడు, UI లేదా అప్లికేషన్ యొక్క ఇతర భాగాలలో నవీకరణలను ప్రేరేపించడానికి set
ట్రాప్ ఉపయోగించబడుతుంది.
ఇక్కడ ఒక అత్యంత సరళీకృత ఉదాహరణ:
function createObservable(target, callback) {
const handler = {
set(obj, prop, value) {
const result = Reflect.set(obj, prop, value);
callback(prop, value); // మార్పుపై కాల్బ్యాక్ను ప్రేరేపించండి
return result;
}
};
return new Proxy(target, handler);
}
const state = {
count: 0,
message: 'Hello'
};
function render(prop, value) {
console.log(`మార్పు కనుగొనబడింది: ప్రాపర్టీ '${prop}' కు '${value}' సెట్ చేయబడింది. UIని మళ్ళీ రెండరింగ్ చేస్తోంది...`);
}
const observableState = createObservable(state, render);
observableState.count = 1;
// కన్సోల్ అవుట్పుట్: మార్పు కనుగొనబడింది: ప్రాపర్టీ 'count' కు '1' సెట్ చేయబడింది. UIని మళ్ళీ రెండరింగ్ చేస్తోంది...
observableState.message = 'Goodbye';
// కన్సోల్ అవుట్పుట్: మార్పు కనుగొనబడింది: ప్రాపర్టీ 'message' కు 'Goodbye' సెట్ చేయబడింది. UIని మళ్ళీ రెండరింగ్ చేస్తోంది...
3. నెగటివ్ అర్రే ఇండెక్స్లు
ఒక క్లాసిక్ మరియు సరదా ఉదాహరణ ఏమిటంటే, పైథాన్ వంటి భాషల మాదిరిగా నెగటివ్ ఇండెక్స్లకు మద్దతు ఇవ్వడానికి స్థానిక అర్రే ప్రవర్తనను విస్తరించడం, ఇక్కడ -1
చివరి మూలకాన్ని సూచిస్తుంది.
function createNegativeArrayProxy(arr) {
const handler = {
get(target, property) {
const index = Number(property);
if (!Number.isNaN(index) && index < 0) {
// నెగటివ్ ఇండెక్స్ను చివరి నుండి ఒక పాజిటివ్ ఇండెక్స్గా మార్చండి
property = String(target.length + index);
}
return Reflect.get(target, property);
}
};
return new Proxy(arr, handler);
}
const originalArray = ['a', 'b', 'c', 'd', 'e'];
const proxiedArray = createNegativeArrayProxy(originalArray);
console.log(proxiedArray[0]); // అవుట్పుట్: a
console.log(proxiedArray[-1]); // అవుట్పుట్: e
console.log(proxiedArray[-2]); // అవుట్పుట్: d
console.log(proxiedArray.length); // అవుట్పుట్: 5
పనితీరు పరిగణనలు మరియు ఉత్తమ పద్ధతులు
ప్రాక్సీలు చాలా శక్తివంతమైనవి అయినప్పటికీ, అవి ఒక మ్యాజిక్ బుల్లెట్ కాదు. వాటి చిక్కులను అర్థం చేసుకోవడం చాలా ముఖ్యం.
పనితీరు ఓవర్హెడ్
ఒక ప్రాక్సీ ఒక పరోక్ష పొరను పరిచయం చేస్తుంది. ఒక ప్రాక్సీ చేయబడిన ఆబ్జెక్ట్పై ప్రతి ఆపరేషన్ హ్యాండ్లర్ గుండా వెళ్ళాలి, ఇది ఒక సాదా ఆబ్జెక్ట్పై ప్రత్యక్ష ఆపరేషన్తో పోలిస్తే కొద్దిగా ఓవర్హెడ్ను జోడిస్తుంది. చాలా అప్లికేషన్లకు (డేటా ధృవీకరణ లేదా ఫ్రేమ్వర్క్-స్థాయి రియాక్టివిటీ వంటివి), ఈ ఓవర్హెడ్ చాలా తక్కువ. అయితే, మిలియన్ల కొద్దీ ఐటెమ్లను ప్రాసెస్ చేసే టైట్ లూప్ వంటి పనితీరు-క్లిష్టమైన కోడ్లో, ఇది ఒక అడ్డంకిగా మారవచ్చు. పనితీరు ఒక ప్రాథమిక ఆందోళన అయితే ఎల్లప్పుడూ బెంచ్మార్క్ చేయండి.
ప్రాక్సీ ఇన్వేరియంట్స్
ఒక ట్రాప్ టార్గెట్ ఆబ్జెక్ట్ యొక్క స్వభావం గురించి పూర్తిగా అబద్ధం చెప్పలేదు. జావాస్క్రిప్ట్ 'ఇన్వేరియంట్స్' అని పిలువబడే నియమాల సమితిని విధిస్తుంది, ప్రాక్సీ ట్రాప్లు వీటిని పాటించాలి. ఒక ఇన్వేరియంట్ను ఉల్లంఘించడం వలన TypeError
వస్తుంది.
ఉదాహరణకు, deleteProperty
ట్రాప్ కోసం ఒక ఇన్వేరియంట్ ఏమిటంటే, టార్గెట్ ఆబ్జెక్ట్పై సంబంధిత ప్రాపర్టీ నాన్-కాన్ఫిగరబుల్ అయితే అది true
(విజయాన్ని సూచిస్తూ) తిరిగి ఇవ్వలేదు. ఇది తొలగించలేని ఒక ప్రాపర్టీని తొలగించినట్లుగా ప్రాక్సీ చెప్పుకోవడాన్ని నిరోధిస్తుంది.
const target = {};
Object.defineProperty(target, 'unbreakable', { value: 10, configurable: false });
const handler = {
deleteProperty(target, prop) {
// ఇది ఇన్వేరియంట్ను ఉల్లంఘిస్తుంది
return true;
}
};
const proxy = new Proxy(target, handler);
try {
delete proxy.unbreakable; // ఇది ఒక లోపాన్ని త్రో చేస్తుంది
} catch (e) {
console.error(e.message);
// అవుట్పుట్: 'deleteProperty' on proxy: returned true for non-configurable property 'unbreakable'
}
ప్రాక్సీలను ఎప్పుడు ఉపయోగించాలి (మరియు ఎప్పుడు కాదు)
- వీటికి మంచిది: ఫ్రేమ్వర్క్లు మరియు లైబ్రరీలను నిర్మించడం (ఉదా., స్టేట్ మేనేజ్మెంట్, ORMs), డీబగ్గింగ్ మరియు లాగింగ్, బలమైన ధృవీకరణ వ్యవస్థలను అమలు చేయడం, మరియు అంతర్లీన డేటా నిర్మాణాలను సంగ్రహించే శక్తివంతమైన APIలను సృష్టించడం.
- వీటికి ప్రత్యామ్నాయాలను పరిగణించండి: పనితీరు-క్లిష్టమైన అల్గారిథమ్లు, ఒక క్లాస్ లేదా ఒక ఫ్యాక్టరీ ఫంక్షన్ సరిపోయే సాధారణ ఆబ్జెక్ట్ పొడిగింపులు, లేదా ES6 మద్దతు లేని చాలా పాత బ్రౌజర్లకు మద్దతు ఇవ్వవలసి వచ్చినప్పుడు.
ఉపసంహరించుకోగల ప్రాక్సీలు (Revocable Proxies)
మీరు ఒక ప్రాక్సీని 'ఆఫ్' చేయవలసిన సందర్భాల కోసం (ఉదా., భద్రతా కారణాల కోసం లేదా మెమరీ నిర్వహణ కోసం), జావాస్క్రిప్ట్ Proxy.revocable()
ను అందిస్తుంది. ఇది ప్రాక్సీ మరియు ఒక revoke
ఫంక్షన్ను రెండింటినీ కలిగి ఉన్న ఒక ఆబ్జెక్ట్ను తిరిగి ఇస్తుంది.
const target = { data: 'sensitive' };
const handler = {};
const { proxy, revoke } = Proxy.revocable(target, handler);
console.log(proxy.data); // అవుట్పుట్: sensitive
// ఇప్పుడు, మనం ప్రాక్సీ యొక్క యాక్సెస్ను ఉపసంహరించుకుంటాము
revoke();
try {
console.log(proxy.data); // ఇది ఒక లోపాన్ని త్రో చేస్తుంది
} catch (e) {
console.error(e.message);
// అవుట్పుట్: Cannot perform 'get' on a proxy that has been revoked
}
ప్రాక్సీలు vs. ఇతర మెటాప్రోగ్రామింగ్ టెక్నిక్లు
ప్రాక్సీలకు ముందు, డెవలపర్లు ఇలాంటి లక్ష్యాలను సాధించడానికి ఇతర పద్ధతులను ఉపయోగించారు. ప్రాక్సీలు ఎలా పోల్చబడతాయో అర్థం చేసుకోవడం ఉపయోగకరంగా ఉంటుంది.
`Object.defineProperty()`
Object.defineProperty()
నిర్దిష్ట ప్రాపర్టీల కోసం గెట్టర్లు మరియు సెట్టర్లను నిర్వచించడం ద్వారా ఒక ఆబ్జెక్ట్ను నేరుగా సవరిస్తుంది. ప్రాక్సీలు, మరోవైపు, అసలు ఆబ్జెక్ట్ను అస్సలు సవరించవు; అవి దానిని చుట్టుముడతాయి.
- పరిధి: `defineProperty` ప్రతి-ప్రాపర్టీ ప్రాతిపదికన పనిచేస్తుంది. మీరు చూడాలనుకుంటున్న ప్రతి ప్రాపర్టీ కోసం మీరు ఒక గెట్టర్/సెట్టర్ను నిర్వచించాలి. ఒక ప్రాక్సీ యొక్క
get
మరియుset
ట్రాప్లు గ్లోబల్, ఏదైనా ప్రాపర్టీపై కార్యకలాపాలను పట్టుకుంటాయి, తర్వాత జోడించిన కొత్త వాటితో సహా. - సామర్థ్యాలు: ప్రాక్సీలు
deleteProperty
,in
ఆపరేటర్, మరియు ఫంక్షన్ కాల్స్ వంటి విస్తృత శ్రేణి కార్యకలాపాలను అడ్డగించగలవు, `defineProperty` చేయలేనిది.
ముగింపు: వర్చువలైజేషన్ యొక్క శక్తి
జావాస్క్రిప్ట్ ప్రాక్సీ API కేవలం ఒక తెలివైన ఫీచర్ కంటే ఎక్కువ; ఇది మనం ఆబ్జెక్ట్లను ఎలా డిజైన్ చేయవచ్చు మరియు వాటితో ఎలా పరస్పరం వ్యవహరించవచ్చు అనే దానిలో ఒక ప్రాథమిక మార్పు. ప్రాథమిక కార్యకలాపాలను అడ్డగించి, అనుకూలీకరించడానికి మనకు అనుమతించడం ద్వారా, ప్రాక్సీలు శక్తివంతమైన ప్యాటర్న్ల ప్రపంచానికి తలుపులు తెరుస్తాయి: అతుకులు లేని డేటా ధృవీకరణ మరియు పరివర్తన నుండి ఆధునిక యూజర్ ఇంటర్ఫేస్లను శక్తివంతం చేసే రియాక్టివ్ సిస్టమ్ల వరకు.
అవి చిన్న పనితీరు వ్యయంతో మరియు అనుసరించాల్సిన నియమాల సమితితో వచ్చినప్పటికీ, శుభ్రమైన, విడదీయబడిన, మరియు శక్తివంతమైన సంగ్రహణలను సృష్టించే వాటి సామర్థ్యం అసమానమైనది. ఆబ్జెక్ట్లను వర్చువలైజ్ చేయడం ద్వారా, మీరు మరింత బలమైన, నిర్వహించదగిన, మరియు వ్యక్తీకరణాత్మకమైన వ్యవస్థలను నిర్మించవచ్చు. తదుపరిసారి మీరు డేటా నిర్వహణ, ధృవీకరణ, లేదా పరిశీలనతో కూడిన సంక్లిష్ట సవాలును ఎదుర్కొన్నప్పుడు, ప్రాక్సీ ఉద్యోగానికి సరైన సాధనమా అని పరిగణించండి. ఇది మీ టూల్కిట్లో అత్యంత సొగసైన పరిష్కారం కావచ్చు.