જાવાસ્ક્રિપ્ટ પ્રોક્સી 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 '${property}' does not exist.`;
}
};
const userProxy = new Proxy(user, userHandler);
console.log(userProxy.firstName); // આઉટપુટ: John
console.log(userProxy.age); // આઉટપુટ: 30
console.log(userProxy.country); // આઉટપુટ: Property 'country' does not exist.
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('Age must be an integer.');
}
if (value <= 0) {
throw new RangeError('Age must be a positive number.');
}
}
// જો વેલિડેશન પાસ થાય, તો ટાર્ગેટ ઓબ્જેક્ટ પર વેલ્યુ સેટ કરો.
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); // આઉટપુટ: Age must be an integer.
}
try {
personProxy.age = -5; // RangeError ફેંકશે
} catch (e) {
console.error(e.message); // આઉટપુટ: Age must be a positive number.
}
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
ઓપરેટરને અસર કરે છે. dataProxy._apiKey
જેવો સીધો એક્સેસ હજુ પણ કામ કરશે સિવાય કે તમે સંબંધિત get
ટ્રેપ પણ લાગુ કરો.
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(`Attempted to delete protected property: '${property}'. Operation denied.`);
return false;
}
return true; // પ્રોપર્ટી ગમે તેમ પણ અસ્તિત્વમાં નહોતી
}
};
const configProxy = new Proxy(immutableConfig, deletionGuardHandler);
delete configProxy.port;
// કન્સોલ આઉટપુટ: Attempted to delete protected property: 'port'. Operation denied.
console.log(configProxy.port); // આઉટપુટ: 8080 (તે ડિલીટ થઈ ન હતી)
ઓબ્જેક્ટ એન્યુમરેશન અને ડિસ્ક્રિપ્શન ટ્રેપ્સ
5. `ownKeys(target)`
આ ટ્રેપ એવા ઓપરેશન્સ દ્વારા ટ્રિગર થાય છે જે ઓબ્જેક્ટની પોતાની પ્રોપર્ટીઝની સૂચિ મેળવે છે, જેમ કે Object.keys()
, Object.getOwnPropertyNames()
, Object.getOwnPropertySymbols()
, અને Reflect.ownKeys()
.
ઉદાહરણ: કીઝ (Keys) ફિલ્ટર કરવી.
ચાલો આને આપણા અગાઉના 'પ્રાઇવેટ' પ્રોપર્ટી ઉદાહરણ સાથે જોડીએ જેથી તેમને સંપૂર્ણપણે છુપાવી શકાય.
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(`Calling function '${target.name}' with arguments: ${argumentsList}`);
// મૂળ ફંક્શનને સાચા કોન્ટેક્સ્ટ અને આર્ગ્યુમેન્ટ્સ સાથે એક્ઝિક્યુટ કરો
const result = Reflect.apply(target, thisArg, argumentsList);
console.log(`Function '${target.name}' returned: ${result}`);
return result;
}
};
const proxiedSum = new Proxy(sum, loggingHandler);
proxiedSum(5, 10);
// કન્સોલ આઉટપુટ:
// Calling function 'sum' with arguments: 5,10
// Function 'sum' returned: 15
7. `construct(target, argumentsList, newTarget)`
આ ટ્રેપ ક્લાસ અથવા ફંક્શનની પ્રોક્સી પર new
ઓપરેટરના ઉપયોગને ઇન્ટરસેપ્ટ કરે છે.
ઉદાહરણ: સિંગલટન પેટર્નનો અમલ.
class MyDatabaseConnection {
constructor(url) {
this.url = url;
console.log(`Connecting to ${this.url}...`);
}
}
let instance;
const singletonHandler = {
construct(target, argumentsList) {
if (!instance) {
console.log('Creating new instance.');
instance = Reflect.construct(target, argumentsList);
}
console.log('Returning existing instance.');
return instance;
}
};
const ProxiedConnection = new Proxy(MyDatabaseConnection, singletonHandler);
const conn1 = new ProxiedConnection('db://primary');
// કન્સોલ આઉટપુટ:
// Creating new instance.
// Connecting to db://primary...
// Returning existing instance.
const conn2 = new ProxiedConnection('db://secondary'); // URL અવગણવામાં આવશે
// કન્સોલ આઉટપુટ:
// Returning existing instance.
console.log(conn1 === conn2); // આઉટપુટ: true
console.log(conn1.url); // આઉટપુટ: db://primary
console.log(conn2.url); // આઉટપુટ: db://primary
વ્યવહારુ ઉપયોગના કેસો અને અદ્યતન પેટર્ન્સ
હવે જ્યારે આપણે વ્યક્તિગત ટ્રેપ્સને આવરી લીધા છે, ચાલો જોઈએ કે વાસ્તવિક દુનિયાની સમસ્યાઓ ઉકેલવા માટે તેમને કેવી રીતે જોડી શકાય છે.
1. API એબ્સ્ટ્રેક્શન અને ડેટા ટ્રાન્સફોર્મેશન
APIs ઘણીવાર એવા ફોર્મેટમાં ડેટા પરત કરે છે જે તમારી એપ્લિકેશનના નિયમો સાથે મેળ ખાતો નથી (દા.ત., snake_case
વિ. 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(`CHANGE DETECTED: The property '${prop}' was set to '${value}'. Re-rendering UI...`);
}
const observableState = createObservable(state, render);
observableState.count = 1;
// કન્સોલ આઉટપુટ: CHANGE DETECTED: The property 'count' was set to '1'. Re-rendering UI...
observableState.message = 'Goodbye';
// કન્સોલ આઉટપુટ: CHANGE DETECTED: The property 'message' was set to 'Goodbye'. Re-rendering UI...
3. નેગેટિવ એરે ઇન્ડેક્સ
એક ક્લાસિક અને મનોરંજક ઉદાહરણ એ છે કે નેગેટિવ ઇન્ડેક્સને સપોર્ટ કરવા માટે મૂળ એરે વર્તણૂકને વિસ્તારવી, જ્યાં -1
છેલ્લા એલિમેન્ટનો સંદર્ભ આપે છે, જે Python જેવી ભાષાઓ જેવું જ છે.
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), ડિબગીંગ અને લોગિંગ, મજબૂત વેલિડેશન સિસ્ટમ્સનો અમલ કરવો, અને શક્તિશાળી APIs બનાવવી જે અંતર્ગત ડેટા સ્ટ્રક્ચર્સને એબ્સ્ટ્રેક્ટ કરે છે.
- આ માટે વિકલ્પો ધ્યાનમાં લો: પર્ફોર્મન્સ-ક્રિટિકલ એલ્ગોરિધમ્સ, સરળ ઓબ્જેક્ટ એક્સ્ટેન્શન્સ જ્યાં ક્લાસ અથવા ફેક્ટરી ફંક્શન પૂરતું હશે, અથવા જ્યારે તમારે ખૂબ જૂના બ્રાઉઝર્સને સપોર્ટ કરવાની જરૂર હોય જેમાં ES6 સપોર્ટ ન હોય.
રિવોકેબલ પ્રોક્સીઝ
એવા સંજોગો માટે જ્યાં તમારે પ્રોક્સીને 'બંધ' કરવાની જરૂર પડી શકે છે (દા.ત., સુરક્ષા કારણોસર અથવા મેમરી મેનેજમેન્ટ માટે), જાવાસ્ક્રિપ્ટ 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
}
પ્રોક્સીઝ વિ. અન્ય મેટાપ્રોગ્રામિંગ તકનીકો
પ્રોક્સીઝ પહેલાં, ડેવલપર્સ સમાન લક્ષ્યો પ્રાપ્ત કરવા માટે અન્ય પદ્ધતિઓનો ઉપયોગ કરતા હતા. પ્રોક્સીઝની તુલના કેવી રીતે થાય છે તે સમજવું ઉપયોગી છે.
`Object.defineProperty()`
Object.defineProperty()
ચોક્કસ પ્રોપર્ટીઝ માટે ગેટર્સ અને સેટર્સ વ્યાખ્યાયિત કરીને સીધા ઓબ્જેક્ટમાં ફેરફાર કરે છે. બીજી બાજુ, પ્રોક્સીઝ મૂળ ઓબ્જેક્ટમાં બિલકુલ ફેરફાર કરતા નથી; તેઓ તેને રેપ કરે છે.
- સ્કોપ: `defineProperty` પ્રોપર્ટી-દીઠ ધોરણે કામ કરે છે. તમારે દરેક પ્રોપર્ટી માટે ગેટર/સેટર વ્યાખ્યાયિત કરવું આવશ્યક છે જેને તમે વોચ કરવા માંગો છો. પ્રોક્સીના
get
અનેset
ટ્રેપ્સ ગ્લોબલ હોય છે, જે કોઈપણ પ્રોપર્ટી પરના ઓપરેશન્સને પકડે છે, જેમાં પાછળથી ઉમેરાયેલી નવી પ્રોપર્ટીઝનો પણ સમાવેશ થાય છે. - ક્ષમતાઓ: પ્રોક્સીઝ
deleteProperty
,in
ઓપરેટર, અને ફંક્શન કૉલ્સ જેવા વ્યાપક ઓપરેશન્સને ઇન્ટરસેપ્ટ કરી શકે છે, જે `defineProperty` કરી શકતું નથી.
નિષ્કર્ષ: વર્ચ્યુઅલાઈઝેશનની શક્તિ
જાવાસ્ક્રિપ્ટ પ્રોક્સી API એ માત્ર એક ચતુર સુવિધા કરતાં વધુ છે; તે આપણે ઓબ્જેક્ટ્સને કેવી રીતે ડિઝાઇન અને તેની સાથે ક્રિયાપ્રતિક્રિયા કરી શકીએ છીએ તેમાં એક મૂળભૂત પરિવર્તન છે. આપણને મૂળભૂત ઓપરેશન્સને ઇન્ટરસેપ્ટ અને કસ્ટમાઇઝ કરવાની મંજૂરી આપીને, પ્રોક્સીઝ શક્તિશાળી પેટર્ન્સની દુનિયાના દરવાજા ખોલે છે: સીમલેસ ડેટા વેલિડેશન અને ટ્રાન્સફોર્મેશનથી લઈને આધુનિક યુઝર ઇન્ટરફેસને શક્તિ આપતી રિએક્ટિવ સિસ્ટમ્સ સુધી.
જ્યારે તેઓ થોડી પર્ફોર્મન્સ કિંમત અને પાલન કરવાના નિયમોના સમૂહ સાથે આવે છે, ત્યારે ક્લીન, ડીકપલ્ડ અને શક્તિશાળી એબ્સ્ટ્રેક્શન્સ બનાવવાની તેમની ક્ષમતા અજોડ છે. ઓબ્જેક્ટ્સને વર્ચ્યુઅલાઈઝ કરીને, તમે એવી સિસ્ટમ્સ બનાવી શકો છો જે વધુ મજબૂત, જાળવી શકાય તેવી અને અભિવ્યક્ત હોય. આગલી વખતે જ્યારે તમે ડેટા મેનેજમેન્ટ, વેલિડેશન અથવા ઓબ્ઝર્વેબિલિટી સંબંધિત કોઈ જટિલ પડકારનો સામનો કરો, ત્યારે વિચારો કે શું પ્રોક્સી તે કામ માટે યોગ્ય સાધન છે. તે તમારા ટૂલકિટમાં સૌથી ઉત્કૃષ્ટ ઉકેલ હોઈ શકે છે.