اÙÙØ§Ø¦Ù Proxy ÙÙØÙØ· ÙØ§Ø¦Ù آخر Ù ÙØªÙسط Ø§ÙØ¹Ù
ÙÙØ§Øª Ø§ÙØªÙ ØªÙØ¬Ø±Ù عÙÙ ÙØ°Ø§ اÙÙØ§Ø¦ÙØ Ù
ث٠اÙÙØ±Ø§Ø¡Ø© Ø£Ù Ø§ÙØªØ¹Ø¯Ù٠عÙÙ Ø§ÙØ®ØµØ§Ø¦Øµ ÙØºÙØ±ÙØ§ ÙØ§ÙتعاÙ
Ù Ù
عÙÙ
بشÙÙ Ø§Ø®ØªÙØ§Ø±Ù أ٠تجع٠اÙÙØ§Ø¦Ù Ø§ÙØ£Ø³Ø§Ø³Ù ÙØªØ¹Ø§Ù
Ù Ù
عÙÙ
دÙ٠تدخÙ.
إ٠اÙÙProxies Ù ÙØ³ØªØ®Ø¯Ù Ø© ÙÙ ÙØ«Ùر ٠٠اÙÙ ÙØªØ¨Ø§Øª ÙØ¨Ø¹Ø¶ أطر Ø§ÙØ¹Ù Ù. Ø³ÙØ±Ù اÙÙØ«Ùر Ù Ù Ø§ÙØªØ·Ø¨ÙÙØ§Øª Ø§ÙØ¹Ù ÙÙØ© ÙÙ ÙØ°Ø§ اÙÙ ÙØ§Ù.
اÙÙØ³ÙØ· Proxy
Ø§ÙØ´ÙÙ:
let proxy = new Proxy(target, handler);
targetâ Ù٠اÙÙØ§Ø¦Ù Ø§ÙØ°Ù ÙØªÙ Ø¥ØØ§Ø·ØªÙ ÙÙÙ Ù٠أ٠ÙÙÙÙ Ø£Ù Ø´ÙØ¦ ØØªÙ Ø§ÙØ¯Ùا٠(functions).handlerâ Ø¥Ø¹Ø¯Ø§Ø¯Øª اÙÙproxy: ÙÙ ÙØ§Ø¦Ù ÙØØªÙ٠عÙÙ âtrapsâ ÙØ§Ùت٠Ù٠عبارة Ø¹Ù Ø¯ÙØ§Ù تع٠٠ÙÙ Ø§ÙØ¹Ù ÙÙØ§Øª. Ù Ø«ÙÙØ§ اÙÙgettrap ÙÙØ±Ø§Ø¡Ø© Ø®Ø§ØµÙØ© ٠٠اÙÙobjecttargetÙÙØ°ÙÙsettrap ÙØªØ¹Ø¯ÙÙ\Ø¥Ø¶Ø§ÙØ© Ø®Ø§ØµÙØ© ÙÙÙobjecttargetÙÙÙØ°Ø§.
باÙÙØ³Ø¨Ø© ÙÙØ¹Ù
ÙÙØ§Øª Ù٠اÙÙ proxyØ ÙØ¥Ù٠إذا ÙØ§Ù ÙÙØ§Ù trap Ù٠اÙÙobject handler ÙØ«Ù
بعد ذÙ٠تعÙ
Ù ÙØ¨Ø¹Ø¯ ذÙÙ ÙÙÙÙ ÙØ¯ÙÙØ§ اÙÙØ±ØµØ© ÙÙØªØ¹Ø§Ù
Ù Ù
Ø¹Ù ÙØ¥Ø°Ø§ ÙÙ
ÙÙØ¬Ø¯ trap ÙØ¥Ù Ø§ÙØ¹Ù
ÙÙØ© ØªÙØ¬Ø±Ù عÙÙ target.
ÙÙ Ø«Ø§Ù Ù Ø¨Ø¯Ø£ÙØ ÙÙØ§ ÙÙØ´Ø¦ proxy بدÙÙ traps:
let target = {};
let proxy = new Proxy(target, {}); // handler ÙØ§Ø±Øº
proxy.test = 5; // Ø§ÙØªØ¹Ø¯Ù٠عÙÙ Ø§ÙØ¨Ø±ÙÙØ³Ù (1)
alert(target.test); // 5, ظÙÙØ± Ø§ÙØ®Ø§ØµÙØ© Ù٠اÙÙØ§Ø¦Ù Ø§ÙØ£ØµÙÙ!
alert(proxy.test); // 5, ÙÙÙ
ÙÙÙØ§ ÙØ±Ø§Ø¦ØªÙ Ù
Ù Ø§ÙØ¨Ø±ÙÙØ³Ù Ø£ÙØ¶Ùا (2)
for (let key in proxy) alert(key); // test, Ø§ÙØªÙرار ÙØ¹Ù
Ù (3)
ÙØ¨Ù
ا Ø£ÙÙ ÙØ§ ØªÙØ¬Ø¯ traps ÙØ¥Ù ÙÙ Ø§ÙØ¹Ù
ÙÙØ§Øª Ø§ÙØªÙ Ø§ÙØªÙ ØªÙØ¬Ø±Ù عÙ٠اÙÙ proxy ÙØªÙ
تØÙÙÙÙØ§ Ø¥Ù٠اÙÙ target.
- عÙ
ÙÙØ© Ø§ÙØªØ¹Ø¯ÙÙ
proxy.test=ØªÙØ¹Ø¯Ù اÙÙÙÙ Ø© Ù٠اÙÙtarget. - عÙ
ÙÙØ© اÙÙØ±Ø§Ø¡Ø©
proxy.testتÙÙ٠بإرجاع اÙÙÙÙ Ø© Ù Ùtarget. - Ø§ÙØªÙرار عÙ٠اÙÙ
proxyÙÙÙ٠بإرجاع اÙÙÙÙ Ù Ùtarget.
ÙÙ
ا ÙØ±Ù ÙØ¥Ù اÙÙproxy بدÙÙ traps ÙÙ Ù
ØÙØ· Ø´ÙØ§Ù ØÙÙ target. أ٠أÙÙ ÙØ§ ÙÙØ¹Ù Ø£Ù Ø´ÙØ¦ Ù٠اÙÙ
ÙØªØµÙ.
Proxyإ٠اÙÙ ÙØ§Ø¦Ù Ù
Ù ÙÙØ¹ خاص ÙØ§ ÙØØªÙ٠عÙ٠أ٠خصائص ÙØ¹ÙدÙ
ا ÙÙÙÙ handler ÙØ§Ø±ØºÙا ÙØ¥ÙÙ ÙØÙÙÙ ÙÙ Ø§ÙØ¹Ù
ÙÙØ§Øª Ø¥ÙÙ target.
ÙÙØØµÙ٠عÙÙ ÙØ¯Ø±Ø§Øª Ø£ÙØ«Ø± ÙÙØ§ ÙØ¶ÙÙ traps.
٠اذا ÙÙ ÙÙÙØ§ Ø£Ù ÙØªØ¯Ø®ÙÙ (intercept) بÙÙ Ø
ÙØ£ØºÙب Ø§ÙØ¹Ù
ÙÙØ§Øª عÙ٠اÙÙobjects ØªÙØ¬Ø¯ Ø¯ÙØ§Ù تسÙ
Ù âØ§ÙØ¯ÙØ§Ù Ø§ÙØ¯Ø§Ø®ÙÙØ©â âinternal methodâ ÙÙ Ù
صدر Ø¬Ø§ÙØ§ Ø³ÙØ±Ùبت ÙØ§Ùت٠تص٠ÙÙÙÙØ© عÙ
ÙÙØ§ Ø¹ÙØ¯ Ø£ÙÙ Ù
ستÙÙ. عÙ٠سبÙ٠اÙÙ
Ø«Ø§Ù Ø§ÙØ¯Ø§ÙØ© [[Get]] ÙÙ Ø¯Ø§ÙØ© داخÙÙØ© ÙÙØ±Ø§Ø¡Ø© Ø®Ø§ØµÙØ© ÙØ§ÙØ¯Ø§ÙØ© [[Set]] ÙÙ Ø¯Ø§ÙØ© داخÙÙØ© ÙØ¥Ø¶Ø§ÙØ©\تعدÙÙ Ø®Ø§ØµÙØ© ÙÙÙØ°Ø§. ÙØ°Ù Ø§ÙØ¯Ùا٠تستخدÙ
ÙÙØ· داخÙÙÙØ§ ÙÙØ§ ÙÙ
ÙÙÙØ§ استعÙ
اÙÙÙ
بشÙÙ Ù
باشر.
تتدخÙ٠اÙÙ Proxy traps Ù٠استدعاء ÙØ°Ù Ø§ÙØ¯ÙاÙ. ÙÙÙ Ù ÙØ¬ÙدÙÙ Ø¨Ø§ÙØªÙصÙÙ Ù٠اÙ٠صدر ÙÙÙ Ø§ÙØ¬Ø¯ÙÙ Ø£Ø¯ÙØ§Ù.
ÙÙÙ Ø¯Ø§ÙØ© داخÙÙØ© ÙÙØ¬Ø¯ trap ÙÙ ÙØ°Ø§ Ø§ÙØ¬Ø¯ÙÙ: اسÙ
Ø§ÙØ¯Ø§ÙØ© Ø§ÙØªÙ ÙÙ
ÙÙÙØ§ Ø¥Ø¶Ø§ÙØªÙا ÙÙÙ
ØªØºÙØ± Ø§ÙØ°Ù ÙØ³Ù
Ù handler ÙØ§ÙØ°Ù ÙØ¶ÙÙÙ ÙÙÙ new Proxy ÙÙØªØ¯Ø®Ù ÙÙ Ø§ÙØ¹Ù
ÙÙØ©:
| Internal Method | Handler Method | Triggers when⦠|
|---|---|---|
[[Get]] |
get |
reading a property |
[[Set]] |
set |
writing to a property |
[[HasProperty]] |
has |
in operator |
[[Delete]] |
deleteProperty |
delete operator |
[[Call]] |
apply |
function call |
[[Construct]] |
construct |
new operator |
[[GetPrototypeOf]] |
getPrototypeOf |
Object.getPrototypeOf |
[[SetPrototypeOf]] |
setPrototypeOf |
Object.setPrototypeOf |
[[IsExtensible]] |
isExtensible |
Object.isExtensible |
[[PreventExtensions]] |
preventExtensions |
Object.preventExtensions |
[[DefineOwnProperty]] |
defineProperty |
Object.defineProperty, Object.defineProperties |
[[GetOwnProperty]] |
getOwnPropertyDescriptor |
Object.getOwnPropertyDescriptor, for..in, Object.keys/values/entries |
[[OwnPropertyKeys]] |
ownKeys |
Object.getOwnPropertyNames, Object.getOwnPropertySymbols, for..in, Object.keys/values/entries |
ØªÙØ±Ø¶ Ø¬Ø§ÙØ§ Ø³ÙØ±Ùبت بعض Ø§ÙØ«Ùابت â Ø´Ø±ÙØ· ÙØ¬Ø¨ أ٠تتØÙ٠باÙmethods ٠اÙtraps.
Ø£ØºÙØ¨ÙÙ ÙØ¥Ø±Ø¬Ø§Ø¹ ÙÙÙ :
- Ø§ÙØ¯Ø§ÙØ©
[[Set]]ÙØ¬Ø¨ أ٠تÙÙ٠بإرجاعtrueإذا ÙÙØªØ¨Øª اÙÙÙÙ Ø© بشÙ٠صØÙØ Ø£Ù ØªÙÙ٠بإرجاعfalseإذا Ù٠تÙÙ ÙØ°ÙÙ. - Ø§ÙØ¯Ø§ÙØ©
[[Delete]]ÙØ¬Ø¨ Ø£Ù Ø§ÙØ©Ù بإرجاعtrueإذا ØªÙ ØØ°Ù اÙÙÙÙ Ø© بشÙ٠صØÙØ ÙØ¥Ùا تÙÙ٠بإرجاعfalse. - â¦ÙÙÙØ°Ø§Ø ÙØ³Ùر٠اÙÙ Ø²ÙØ¯ ÙÙ Ø§ÙØ£Ù Ø«ÙØ© اÙÙØ§Ø¯Ù Ø©.
ÙÙØ§Ù اÙÙ Ø²ÙØ¯ Ù Ù Ø§ÙØ«ÙØ§Ø¨ØªØ Ù Ø«ÙÙØ§:
- Ø§ÙØ¯Ø§ÙØ©
[[GetPrototypeOf]]اÙÙ ÙØ¬Ùدة ÙÙ Ø§ÙØ¨Ø±ÙÙØ³ÙØ ÙØ¬Ø¨ Ø£Ù ØªÙØ±Ø¬Ø¹ ÙÙØ³ اÙÙÙÙ Ø© Ø§ÙØªÙ ØªÙØ±Ø¬Ø¹Ùا Ø§ÙØ¯Ø§ÙØ©[[GetPrototypeOf]]اÙÙ ÙØ¬Ùدة ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¯Ù (target). Ø£Ù ÙÙ ÙÙÙØ§ اÙÙÙ٠بطرÙÙØ© Ø£Ø®Ø±ÙØ أ٠استرجاع اÙÙÙ٠٠٠اÙprototype Ø§ÙØ®Ø§Øµ Ø¨Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØ¬Ø¨ دائ٠ا Ø£Ù ØªÙØ±Ø¬Ø¹ اÙprototype Ø§ÙØ®Ø§Øµ Ø¨Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¯Ù (target).
ØªØ³ØªØ·ÙØ¹ اÙtraps أ٠تعترض طرÙÙ ÙØ°Ù Ø§ÙØ¹Ù ÙÙØ§ØªØ ÙÙÙÙ ÙØ¬Ø¨ Ø£Ù ÙØªØ¨Ø¹Ù ÙØ°Ù اÙÙÙØ§Ø¹Ø¯.
ØªØ¶Ù Ù Ø§ÙØ«Ùابت ØµØØ© ÙØªÙاس٠سÙÙÙ Ù Ø²Ø§ÙØ§ اÙÙØºØ©. ÙÙÙØ¥Ø·Ùاع عÙ٠اÙÙØ§Ø¦Ù Ø© اÙÙØ§Ù ÙØ© ÙÙØ«Ùابت ÙÙÙ Ù ÙØ¬Ùدة Ù٠اÙ٠صدر. ÙØ§ تÙÙÙØ Ù٠تÙÙ٠ب٠خاÙÙØ© ÙØ°Ù Ø§ÙØ«Ùابت ٠اÙ٠تÙ٠تÙÙÙ Ø¨Ø¹Ù Ù ØºØ±ÙØ¨.
ÙÙØ§ ÙØ±Ù ÙÙÙ ÙØªÙ تطبÙ٠ذÙÙ ÙÙ Ø£Ù Ø«ÙØ© ع٠ÙÙØ©.
إرجاع ÙÙÙ Ø© Ø§ÙØªØ±Ø§Ø¶ÙØ© باÙtrap âgetâ
Ø£ÙØ«Ø± اÙtraps استع٠اÙÙØ§ Ø§ÙØªÙ تسترجع Ø£Ù ØªØ¹Ø¯Ù Ø§ÙØ®ØµØ§Ø¦Øµ (properties).
ÙØ§Ø¹ØªØ±Ø§Ø¶ طرÙ٠عÙ
ÙÙØ© Ø§ÙØ¥Ø³ØªØ±Ø¬Ø§Ø¹Ø ÙØ¬Ø¨ Ø£Ù ÙØØªÙ٠اÙhandler عÙÙ Ø§ÙØ¯Ø§ÙØ© get(target, property, receiver).
ÙØªÙ تشغÙÙÙØ§ Ø¹ÙØ¯Ù ا تÙÙÙ Ø§ÙØ®Ø§ØµÙØ© ÙÙØ¥Ø³ØªØ±Ø¬Ø§Ø¹ باÙÙ ØªØºÙØ±Ø§Øª Ø§ÙØªØ§ÙÙØ©:
targetâ ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¯Ù ÙØ§ÙØ°Ù ÙØªÙ ØªÙ Ø±ÙØ±Ù ÙÙ ØªØºÙØ± Ø£ÙÙ ÙÙnew Proxy,propertyâ Ø§Ø³Ù Ø§ÙØ®Ø§ØµÙØ©,receiverâ Ø¥Ø°Ø§ ÙØ§Ùت Ø§ÙØ®Ø§ØµÙØ© ÙÙØ¥Ø³ØªØ±Ø¬Ø§Ø¹ getter ÙØ¥Ù اÙreceiverÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª Ø§ÙØ°Ù Ø³ÙØªÙ استخدا٠٠ÙÙÙÙ Ø© ÙthisØ¹ÙØ¯ Ø§Ø³ØªØ±Ø¬Ø§Ø¹ÙØ§. ÙØ¹Ø§Ø¯Ø© ٠اÙÙÙÙ Ø§ÙØ¨Ø±ÙÙØ³Ù ÙÙØ³Ù (Ø£Ù Ø£ÙØ¨Ø¬Ùت ÙØ±Ø« Ù ÙÙ). ÙØ§ÙØ¢Ù ÙØ§ ÙØ±Ùد ÙØ°Ø§ اÙÙ ØªØºÙØ±Ø ÙÙØ°ÙÙ Ø³ÙØªÙ شرØÙ ÙØ§ØÙÙØ§ Ø¨Ø§ÙØªÙصÙÙ.
ÙÙØ§ ÙØ³ØªØ®Ø¯Ù
get ÙØªØ·Ø¨Ù٠اÙÙÙÙ
Ø© Ø§ÙØ¥ÙØªØ±Ø§Ø¶ÙØ© ÙØ£ÙØ¨Ø¬ÙØª.
سÙÙÙÙ
Ø¨Ø¥ÙØ´Ø§Ø¡ array ØªØØªÙ٠عÙÙ Ø£Ø±ÙØ§Ù
ÙØ§Ùت٠تÙÙÙ
بإرجاع 0 ÙÙÙÙÙ
Ø§ÙØºÙر Ù
ÙØ¬Ùدة.
Ø¹Ø§Ø¯Ø©Ø Ø¹ÙØ¯Ù
ا ÙØØ§ÙÙ Ø£ØØ¯ Ø£Ù ÙØ³ØªØ±Ø¬Ø¹ ÙÙÙ
Ø© ØºÙØ± Ù
ÙØ¬Ùدة Ù٠اÙarray ÙØ¥ÙÙ ÙØØµÙ Ø¹ÙÙ undefined, ÙÙÙÙÙØ§ Ø³ÙØÙØ· اÙarray Ø§ÙØ¹Ø§Ø¯ÙØ© ببرÙÙØ³Ù ÙØ§ÙØ°Ù Ø³ÙØ¹ØªØ±Ø¶ عÙ
ÙÙØ© Ø§ÙØ§Ø³ØªØ±Ø¬Ø§Ø¹ ÙÙÙÙÙ
بإرجاع 0 إذا ÙÙ
ØªÙØ¬Ø¯ Ø§ÙØ®Ø§ØµÙØ©:
let numbers = [0, 1, 2];
numbers = new Proxy(numbers, {
get(target, prop) {
if (prop in target) {
return target[prop];
} else {
return 0; // اÙÙÙÙ
Ø© Ø§ÙØ¥ÙØªØ±Ø§Ø¶ÙØ©
}
}
});
alert( numbers[1] ); // 1
alert( numbers[123] ); // 0 (ÙØ§ ÙÙØ¬Ø¯ Ø¹ÙØµØ± ÙÙØ°Ø§)
ÙÙ
ا ÙØ±ÙØ ÙØ£Ù ÙØ°Ø§ ÙÙ
Ù٠تØÙÙÙ٠بسÙÙÙ٠باستخداÙ
اÙtrap get.
ÙÙ
ÙÙÙØ§ استخداÙ
Proxy ÙØªØ·Ø¨Ù٠أ٠طرÙÙØ© ÙÙÙÙÙ
Ø§ÙØ¥ÙØªØ±Ø§Ø¶ÙØ©.
تخÙÙ Ø£Ù ÙØ¯ÙÙØ§ ÙØ§Ù ÙØ³ÙØ§Ø Ø¨Ø§ÙØ¬Ù Ù ÙØªØ±Ø¬Ù Ø§ØªÙØ§:
let dictionary = {
Hello: 'Ù
Ø±ØØ¨Ùا',
Bye: 'Ø¥Ù٠اÙÙÙØ§Ø¡',
};
alert(dictionary['Hello']); // Ù
Ø±ØØ¨Ùا
alert(dictionary['Welcome']); // undefined
ØØ§ÙÙÙØ§Ø ÙÙØ³Øª ÙÙØ§Ù جÙ
ÙØ©Ø ÙØ¹Ùد Ø§ÙØ¥Ø³ØªØ±Ø¬Ø§Ø¹ Ù
٠اÙÙØ§Ù
ÙØ³ تÙÙÙ
بإرجاع undefined. ÙÙÙÙ ÙÙ Ø§ÙØªØ·Ø¨ÙÙ Ø§ÙØ¹Ù
ÙÙØ ÙØ¥Ù ØªØ±Ù Ø§ÙØ¬Ù
ÙØ© ØºÙØ± Ù
ترجÙ
Ø© Ø£ÙØ¶Ù Ù
Ù undefined. ÙÙØ°ÙÙ Ø³ÙØ¬Ø¹ÙÙØ§ تÙÙÙ
بإرجاع Ø§ÙØ¬Ù
ÙØ© ØºÙØ± Ù
ترجÙ
Ø© بدÙÙØ§ Ù
Ù undefined.
ÙØªØÙÙ٠ذÙÙØ Ø³ÙØÙØ· اÙdictionary ببرÙÙØ³Ù ÙØ§Ùذ٠سÙÙÙÙ
باعتراض طرÙ٠استرجاع Ø§ÙØ®ØµØ§Ø¦Øµ:
let dictionary = {
'Hello': 'Ù
Ø±ØØ¨Ùا',
'Bye': 'Ø¥Ù٠اÙÙÙØ§Ø¡'
};
dictionary = new Proxy(dictionary, {
get(target, phrase) { // تعترض طرÙ٠استرجاع Ø§ÙØ®ØµØ§Ø¦Øµ Ù
٠اÙÙØ§Ù
ÙØ³
if (phrase in target) { // إذا ÙØ§Ùت ÙØ¯ÙÙØ§ باÙÙØ¹Ù
return target[phrase]; // ÙÙ
بإرجاع Ø§ÙØªØ±Ø¬Ù
Ø©
} else {
// ÙØ¥Ùا ÙÙØªÙÙ
بإرجاع Ø§ÙØ¬Ù
ÙØ© ÙÙ
ا ÙÙ
return phrase;
}
}
});
// ÙÙ
Ø¨Ø§ÙØªØ´Ø§Ù Ø§ÙØ¬Ù
Ù Ø§ÙØ§Ø¹ØªØ¨Ø§Ø·ÙØ©!
// ÙÙ Ø£Ø³ÙØ£ Ø§ÙØØ§ÙØª ÙÙ ÙØªÙ
ترجÙ
تÙÙ
.
alert( dictionary['Hello'] ); // Hola
alert( dictionary['Welcome to Proxy']); // Welcome to Proxy (ÙØ§ ØªÙØ¬Ø¯ ترجÙ
Ø©)
ÙØ§ØØ¸ ÙÙÙ ÙØ³ØªØ¨Ø¯Ù Ø§ÙØ¨Ø±ÙÙØ³Ù اÙÙ ØªØºÙØ±:
dictionary = new Proxy(dictionary, ...);
ÙØ¬Ø¨ Ø£Ù ÙÙÙ٠اÙÙ ØªØºÙØ± Ø¨Ø§Ø³ØªØ¨Ø¯Ø§Ù Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¯Ù\اÙÙ Ø³ØªÙØ¨Ù بشÙ٠تا٠. ÙØ¬Ø¨ Ø£ÙØ§ ÙØ³ØªØ·Ùع Ø£ØØ¯ استدعاء Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¨Ù بعد أ٠ت٠ت Ø¥ØØ§Ø·ØªÙ ببرÙÙØ³Ù. ÙØ¥Ùا سÙÙÙÙ Ù Ù Ø§ÙØ³ÙÙ Ø£Ù ØªÙØ³Ø¯ ÙÙ Ø´ÙØ¦.
Ø§ÙØªØÙ٠٠٠اÙÙÙ٠باستخدا٠اÙtrap âsetâ
Ø¯Ø¹ÙØ§ ÙÙÙ٠أÙÙØ§ ÙØ±Ùد array ÙÙØ£Ø±Ùا٠ÙÙØ·. ÙØ¥Ø°Ø§ ت٠ت Ø¥Ø¶Ø§ÙØ© ÙÙÙ Ø© Ù Ù ÙÙØ¹ Ø¢Ø®Ø±Ø ÙØ¬Ø¨ Ø£Ù ÙÙÙÙ ÙÙØ§Ù خطأ.
تعÙ
٠اÙtrap set Ø¹ÙØ¯ Ø§ÙØªØ¹Ø¯Ù٠عÙÙ Ø®Ø§ØµÙØ©.
set(target, property, value, receiver):
targetâ ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¨ÙØ ÙÙ Ø§ÙØ°Ù ÙØªÙ ØªÙ Ø±ÙØ±Ù ÙÙ ØªØºÙØ± Ø£ÙÙ ÙÙnew Proxy,propertyâ Ø¥Ø³Ù Ø§ÙØ®Ø§ØµÙØ©,valueâ ÙÙÙ Ø© Ø§ÙØ®Ø§ØµÙØ©,receiverâ Ø´Ø¨Ù٠باÙJtrapgetØ ÙÙÙÙ Ù ÙÙØ¯ ÙÙØ· ÙÙØ®ØµØ§Ø¦Øµ Ø§ÙØªÙ ÙØªÙ Ø§ÙØªØ¹Ø¯Ù٠عÙÙÙØ§.
ÙØ¬Ø¨ Ø£Ù ÙÙÙÙ
اÙtrap set بإرجاع true إذا ÙØ¬Ø Ø§ÙØªØ¹Ø¯ÙÙØ ÙØ¥Ùا ÙÙÙÙ
بإرجاع false (ÙÙÙÙ
بتشغÙÙ TypeError).
ÙÙØ§ ÙØ³ØªØ®Ø¯Ù Ù ÙÙØªØÙ٠٠٠اÙÙÙÙ Ø§ÙØ¬Ø¯Ùدة:
let numbers = [];
numbers = new Proxy(numbers, { // (*)
set(target, prop, val) { // ÙØ§Ø¹ØªØ±Ø§Ø¶ عÙ
ÙÙØ© Ø§ÙØªØ¹Ø¯ÙÙ
if (typeof val == 'number') {
target[prop] = val;
return true;
} else {
return false;
}
}
});
numbers.push(1); // تÙ
ت Ø¥Ø¶Ø§ÙØªÙ Ø¨ÙØ¬Ø§Ø
numbers.push(2); // تÙ
ت Ø¥Ø¶Ø§ÙØªÙ Ø¨ÙØ¬Ø§Ø
alert("Length is: " + numbers.length); // 2
numbers.push("test"); // TypeError ('set' on proxy returned false)
alert("ÙÙ ÙØªÙ
اÙÙØµÙ٠إÙÙ ÙØ°Ø§ Ø§ÙØ³Ø·Ø± Ø£Ø¨Ø¯Ø§Ø ÙÙÙØ§Ù خطأ ÙÙ Ø§ÙØ³Ø·Ø± Ø§ÙØ£Ø¹ÙÙ");
ÙØ§ØØ¸ Ø£Ù: اÙÙØ¸ÙÙØ© Ø§ÙØ£Ø³Ø§Ø³ÙØ© ÙÙarray Ù
ا Ø²Ø§ÙØª تعÙ
Ù ÙÙ
ا ÙÙ! ØªÙØ¶Ø§Ù اÙÙÙÙ
باستخداÙ
push. ÙØªØ²Ø¯Ø§Ø¯ Ø§ÙØ®Ø§ØµÙØ© length تÙÙØ§Ø¦ÙÙØ§ Ø¹ÙØ¯ Ø¥Ø¶Ø§ÙØ© ÙÙÙ
Ø¬Ø¯ÙØ¯Ø©. ÙØ§ ÙØ¹Ø¯Ù Ø§ÙØ¨Ø±ÙÙØ³Ù Ø£Ù Ø´ÙØ¦.
ÙØ³Ùا Ù
ضطرÙÙ ÙØ§Ø³ØªØ¨Ø¯Ø§Ù Ø§ÙØ¯Ùا٠اÙÙ
سؤÙÙØ© Ø¹Ù Ø¥Ø¶Ø§ÙØ© ÙÙÙ
ÙÙarray Ù
ث٠push Ù unshift, ÙÙÙØ°Ø§, ÙØ¥Ø¶Ø§ÙØ© تØÙÙØ§Øª ÙÙØ§Ù, ÙØ£ÙÙÙ
ضÙ
ÙÙÙØ§ ÙØ³ØªØ®Ø¯Ù
ÙÙ Ø§ÙØ¯Ø§ÙØ© [[Set]] ÙØ§ÙØªÙ ÙØªÙ
Ø§Ø¹ØªØ±Ø§Ø¶ÙØ§ Ø¨Ø§ÙØ¨Ø±ÙÙØ³Ù.
ÙÙÙØ°Ø§ ÙÙÙ٠اÙÙÙØ¯ ÙØ¸ÙÙ ÙÙ ØªÙØ§Ø³Ù.
trueÙ٠ا ÙÙÙ Ø¨Ø§ÙØ£Ø¹ÙÙØ ÙÙØ§Ù Ø«ÙØ§Ø¨Øª ÙØ¬Ø¨ Ø§ÙØ¥ÙØªØ²Ø§Ù Ø¨ÙØ§.
ÙÙÙ Ø§ÙØ¯Ø§ÙØ© setØ ÙØ¬Ø¨ أ٠تÙÙÙ
بإرجاع true ÙÙ Ø§ÙØªØ¹Ø¯Ù٠اÙÙØ§Ø¬Ø.
إذا ÙØ³ÙÙØ§ Ø£Ù ÙÙØ¹Ù ذÙ٠أ٠ÙÙ
ÙØ§ بإرجاع Ø£Ù ÙÙÙ
Ø© ØºÙØ± ØÙÙÙÙØ© (falsy)Ø ÙØªÙÙÙ
Ø§ÙØ¹Ù
ÙÙØ© Ø¨ØªÙØ¹ÙÙ Ø§ÙØ®Ø·Ø£ TypeError.
Ø§ÙØªÙرار باستخدا٠âownKeysâ Ù âgetOwnPropertyDescriptorâ
Ø§ÙØªÙرارات Object.keys, for..in ÙØ£ØºÙب Ø§ÙØ¯ÙØ§Ù Ø§ÙØ£Ø®Ø±Ù اÙÙØªÙ تÙÙÙ
Ø¨Ø§ÙØªÙرار عÙ٠خصائص Ø§ÙØ£ÙØ¨Ø¬ÙØª تستخدÙ
ضÙ
ÙÙÙØ§ Ø§ÙØ¯Ø§ÙØ© [[OwnPropertyKeys]] (ÙØ§ÙØªÙ ÙØªÙ
Ø§Ø¹ØªØ±Ø§Ø¶ÙØ§ ع٠طرÙ٠اÙtrapownKeys) ÙØ§Ø³ØªØ±Ø¬Ø§Ø¹ ÙØ§Ø¦Ù
Ø© Ù
Ù Ø§ÙØ®ØµØ§Ø¦Øµ.
Ø¯ÙØ§Ù ÙÙØ°Ù تختÙÙ ÙÙ Ø§ÙØªÙاصÙÙ:
- تÙÙÙ
Ø§ÙØ¯Ø§ÙØ©
Object.getOwnPropertyNames(obj)بإرجاع Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØªÙ ÙÙØ³Øª Ù Ù ÙÙØ¹ Ø§ÙØ±Ù ز (symbol). - تÙÙÙ
Ø§ÙØ¯Ø§ÙØ©
Object.getOwnPropertySymbols(obj)بإرجاع Ø§ÙØ®ØµØ§Ø¦Øµ Ù Ù ÙÙØ¹ Ø§ÙØ±Ù ز. - تÙÙÙ
Ø§ÙØ¯Ø§ÙØ©
Object.keys/values()بإرجاع Ø§ÙØ®ØµØ§Ø¦Øµ ÙØ§ÙÙÙÙ Ø§ÙØªÙ ÙÙØ³Øª Ù Ù ÙÙØ¹ Ø§ÙØ±Ù ز ÙØ§ÙØªÙ ØªØØªÙ٠عÙ٠اÙ٠عرÙÙenumerable(ØªÙ Ø´Ø±Ø Ø§ÙÙ Ø¹Ø±ÙØ§Øª Ù٠اÙÙ ÙØ§Ù Ø±Ø§ÙØ§Øª Ø§ÙØ®ØµØ§Ø¦Øµ Ù ÙØ§ØµÙØ§ØªÙØ§). - Ø§ÙØªÙرارات
for..inتÙÙÙ Ø¨Ø§ÙØªÙرار عÙÙ Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØªÙ ÙÙØ³Øª Ù Ù ÙÙØ¹ Ø§ÙØ±Ù ز ÙØ§ÙÙ ØØªÙÙØ© عÙ٠اÙ٠عرÙenumerableÙØ£ÙØ¶ÙØ§ Ø§ÙØ®ØµØ§Ø¦Øµ اÙÙ ÙØ¬Ùدة Ù٠اÙprototype.
â¦ÙÙÙÙ Ø¬Ù ÙØ¹ÙÙ ÙØ¨Ø¯Ø£ÙÙ Ø¨ÙØ°Ù اÙÙØ§Ø¦Ù Ø©.
Ù٠اÙÙ
Ø«Ø§Ù Ø£Ø¯ÙØ§Ù استخدÙ
ÙØ§ اÙtrap ownKeys ÙØ¬Ø¹Ù Ø§ÙØªÙرار for..in عÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª userØ ÙÙØ°ÙÙ Object.keys Ù Object.valuesØ ÙØªØ®Ø·Ù Ø§ÙØ®ØµØ§Ø¦Øµ اÙÙØªÙ تبدأ ب٠_:
let user = {
name: "John",
age: 30,
_password: "***"
};
user = new Proxy(user, {
ownKeys(target) {
return Object.keys(target).filter(key => !key.startsWith('_'));
}
});
// "ownKeys" filters out _password
for(let key in user) alert(key); // name, then: age
// same effect on these methods:
alert( Object.keys(user) ); // name,age
alert( Object.values(user) ); // John,30
Ø¥ÙÙØ§ ØªØ¹Ù Ù Ø§ÙØ¢Ù.
عÙÙ Ø§ÙØ±ØºÙ
Ù
٠ذÙÙØ إذا ÙÙ
ÙØ§ بإرجاع Ø®Ø§ØµÙØ© ÙÙØ³Øª Ù
ÙØ¬Ùدة ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª ÙØ¥Ù Object.keys Ù٠تعرضÙ:
let user = { };
user = new Proxy(user, {
ownKeys(target) {
return ['a', 'b', 'c'];
}
});
alert( Object.keys(user) ); // <ÙØ§Ø±Øº>
ÙÙ
Ø§Ø°Ø§Ø Ø§ÙØ³Ø¨Ø¨ Ø¨Ø³ÙØ·: تÙÙÙ
Object.keys بإرجاع Ø§ÙØ®ØµØ§Ø¦Øµ اÙÙ
ØØªÙÙ٠عÙ٠اÙÙ
عر٠enumerable ÙÙØ·. ÙÙØªØÙÙ Ù
٠ذÙÙØ Ù٠تÙÙÙ
باستدعاء Ø§ÙØ¯Ø§ÙØ© [[GetOwnProperty]] ÙÙÙ Ø®Ø§ØµÙØ© ÙØ§Ø³ØªØ±Ø¬Ø§Ø¹ اÙÙ
Ø¹Ø±Ù Ø§ÙØ®Ø§Øµ Ø¨ÙØ§. ÙÙÙØ§Ø بÙ
ا Ø£ÙÙ ÙØ§ ÙÙØ¬Ø¯ Ø®ØµØ§Ø¦ØµØ ÙØ¥Ù Ù
عرÙÙØ§ ÙØ§Ø±ØºØ ÙÙØ§ ÙÙØ¬Ø¯ اÙÙ
عر٠enumerable ÙÙØªÙ
تخطÙÙØ§.
ÙØ¬Ø¹Ù Object.keys تÙÙÙ
بإرجاع Ø®Ø§ØµÙØ©Ø ÙØØªØ§Ø¬ Ø¥Ù٠أ٠تÙÙÙ Ù
ÙØ¬Ùدة ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª ÙÙ
ØØªÙÙØ© عÙ٠اÙÙ
عر٠enumerableØ Ø£Ù ÙÙ
ÙÙÙØ§ اعتراض استدعاء Ø§ÙØ¯Ø§ÙØ© [[GetOwnProperty]] (ÙÙÙÙ
Ø¨ÙØ°Ø§ اÙtrap getOwnPropertyDescriptor)Ø ÙÙÙÙÙ
بإرجاع ÙØ§ØµÙ (descriptor) ÙØ§ÙØ±Ø§ÙØ© enumerable: true.
ÙÙØ§ ٠ثا٠عÙ٠ذÙÙ:
let user = {};
user = new Proxy(user, {
ownKeys(target) {
// ÙØªÙ
Ø§Ø³ØªØ¯Ø¹Ø§Ø¤ÙØ§ Ù
رة ÙØ¥Ø±Ø¬Ø§Ø¹ ÙØ§Ø¦Ù
Ø©
return ['a', 'b', 'c'];
},
getOwnPropertyDescriptor(target, prop) {
// ÙØªÙ
Ø§Ø³ØªØ¯Ø¹Ø§Ø¤ÙØ§ ÙÙÙ Ø®Ø§ØµÙØ©
return {
enumerable: true,
configurable: true,
/* ...other flags, probable "value:..." */
};
},
});
alert(Object.keys(user)); // a, b, c
ÙÙØ§ ÙØ³Ø¬Ù ذÙÙ Ù
رة أخرÙ: ÙØØªØ§Ø¬ ÙØ§Ø¹ØªØ±Ø§Ø¶ [[GetOwnProperty]] ÙÙØ· إذا ÙØ§Ùت Ø§ÙØ®Ø§ØµÙØ© ØºÙØ± Ù
ÙØ¬Ùدة ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª.
Ø§ÙØ®ØµØ§Ø¦Øµ اÙÙ ØÙ ÙØ© باستخدا٠âdeletePropertyâ ÙØºÙر٠٠٠اÙtraps
ÙÙØ§Ù شئ شائع Ù
تÙ٠عÙÙÙ ÙÙÙ Ø£Ù Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØªÙ تبدأ بÙ_ Ù٠ضÙ
ÙÙØ© ÙÙØ§ ÙØ¬Ø¨ Ø£Ù ÙØªÙ
اÙÙØµÙ٠إÙÙÙØ§ Ù
٠خارج Ø§ÙØ£ÙØ¨Ø¬ÙØª.
ÙÙØ°Ø§ Ù Ù Ù٠تÙÙÙÙØ§:
let user = {
name: 'John',
_password: 'secret',
};
alert(user._password); // secret
ÙÙØ§ ÙØ³ØªØ®Ø¯Ù
اÙproxies ÙÙ
ÙØ¹ Ø£Ù ÙØµÙ٠إÙÙ Ø§ÙØ®Ø³Ø§Ø¦Øµ Ø§ÙØ¨Ø§Ø¯Ø¦Ø© ب٠_.
Ø³ÙØØªØ§Ø¬ Ø¥Ù٠اÙtraps:
getÙØ¥Ø·Ùار خطأ Ø¹ÙØ¯ استرجاع Ø®Ø§ØµÙØ© ÙÙØ°Ù,setÙØ¥Ø¸Ùار خطأ Ø¹ÙØ¯ Ø§ÙØªØ¹Ø¯ÙÙ,deletePropertyÙØ¥Ø¸Ùار خطأ Ø¹ÙØ¯ Ø§ÙØØ°Ù,ownKeysÙØ§Ø³ØªØ«Ùاء Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØ¨Ø§Ø¯Ø¦Ø© بÙ_Ù Ù Ø§ÙØªÙرارfor..inÙØ§ÙØ¯ÙØ§Ù Ø§ÙØ£Ø®Ø±Ù Ù Ø«ÙObject.keys.
Ø¥ÙÙ٠اÙÙÙØ¯:
let user = {
name: "John",
_password: "***"
};
user = new Proxy(user, {
get(target, prop) {
if (prop.startsWith('_')) {
throw new Error("Access denied");
}
let value = target[prop];
return (typeof value === 'function') ? value.bind(target) : value; // (*)
},
set(target, prop, val) { // ÙØ§Ø¹ØªØ±Ø§Ø¶ Ø§ÙØªØ¹Ø¯Ù٠عÙÙ Ø§ÙØ®Ø§ØµÙØ©
if (prop.startsWith('_')) {
throw new Error("Access denied");
} else {
target[prop] = val;
return true;
}
},
deleteProperty(target, prop) { // to intercept property deletion
if (prop.startsWith('_')) {
throw new Error("Access denied");
} else {
delete target[prop];
return true;
}
},
ownKeys(target) { // ÙØ§Ø¹ØªØ±Ø§Ø¶ عرض Ø§ÙØ®ØµØ§Ø¦Øµ ÙÙ ÙØ§Ø¦Ù
Ø©
return Object.keys(target).filter(key => !key.startsWith('_'));
}
});
// "get" ÙØ§ تسÙ
Ø Ø¨Ø¥Ø±Ø¬Ø§Ø¹ _password
try {
alert(user._password); // Error: Access denied
} catch(e) { alert(e.message); }
// "set" ÙØ§ تسÙ
Ø Ø¨ØªØ¹Ø¯ÙÙ _password
try {
user._password = "test"; // Error: Access denied
} catch(e) { alert(e.message); }
// "deleteProperty" ÙØ§ تسÙ
ج Ø¨ØØ°Ù _password
try {
delete user._password; // Error: Access denied
} catch(e) { alert(e.message); }
// "ownKeys" تستثÙÙ _password
for(let key in user) alert(key); // name
ÙØ§ØØ¸ Ø§ÙØªÙصÙÙØ© اÙÙ
ÙÙ
Ù Ù٠اÙtrap get ÙÙ Ø§ÙØ³Ø·Ø± (*):
get(target, prop) {
// ...
let value = target[prop];
return (typeof value === 'function') ? value.bind(target) : value; // (*)
}
ÙÙ
اذا ÙØØªØ§Ø¬ Ø¥ÙÙ Ø¯Ø§ÙØ© ÙØ§Ø³ØªØ¯Ø¹Ø§Ø¡ value.bind(target)Ø
ÙØ§Ùسبب Ø£Ù Ø¯ÙØ§Ù Ø£ï»·ÙØ¨Ø¬ÙØªØ Ù
ث٠user.checkPassword()Ø ÙØ¬Ø¨ Ø£Ù ØªÙØ¯Ø± عÙ٠اÙÙØµÙ٠إÙÙ _password:
user = {
// ...
checkPassword(value) {
// Ø¯Ø§ÙØ© Ø§ÙØ£ÙØ¨Ø¬ÙØª ÙØ¬Ø¨ Ø£Ù ØªÙØ¯Ø± عÙ٠اÙÙØµÙ٠إÙÙ _password
return value === this._password;
},
};
استدعاء user.checkPassword() ÙÙÙÙ
بإرجاع user اÙÙ
ÙØØ§Ø· ببرÙÙØ³Ù ÙÙÙÙ
Ø© ÙÙ this (Ø§ÙØ£ÙØ¨Ø¬ÙØª ÙØ¨Ù Ø¹ÙØ§Ù
Ø© اÙÙÙØ·Ø© ÙÙ ÙÙÙ
Ø© this)Ø ÙÙØ°ÙÙ ÙØ¹ÙدÙ
ا ØªØØ§Ù٠اÙÙØµÙ٠إÙÙ this._password ÙÙØ´Ø· اÙÙtrap get (تعÙ
Ù Ù
ع Ù٠استدعاء ÙØ®Ø§ØµÙØ©) ÙØªØ¸Ùر Ø®Ø·Ø£ÙØ§.
A call to user.checkPassword() gets proxied user as this (the object before dot becomes this), so when it tries to access this._password, the get trap activates (it triggers on any property read) and throws an error.
So we bind the context of object methods to the original object, target, in the line (*). Then their future calls will use target as this, without any traps.
ÙØ°Ø§ Ø§ÙØÙ Ø¹Ø§Ø¯Ø© ٠ا ÙØ¹Ù ÙØ ÙÙÙÙÙ ÙÙØ³ ٠ثاÙÙÙØ§Ø ÙØ¥Ù Ø¯Ø§ÙØ© ÙÙØ°Ù ÙÙ ÙÙÙØ§ أ٠ترجع Ø§ÙØ£ÙØ¨Ø¬ÙØª ØºÙØ± Ù ØØ§Ø· ببرÙÙØ³Ù ÙÙ Ø£Ù Ù ÙØ§Ù آخر ÙÙÙØ°Ø§ سÙÙØ³Ø¯ ÙÙ Ø´ÙØ¦: Ø£ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª Ø§ÙØ£ØµÙÙØ ÙØ£Ù٠اÙÙ ØØ§Ø· ببرÙÙØ³ÙØ
Ø¥ÙÙ Ø¬Ø§ÙØ¨ ذÙÙØ ÙØ¥Ù Ø£ÙØ¨Ø¬Ùت ÙÙØ°Ø§ ÙÙ ÙÙ Ø¥ØØ§Ø·ØªÙ ببرÙÙØ³Ù Ø£ÙØ«Ø± ٠٠٠ر٠(Ù٠برÙÙØ³Ù ÙÙ ÙÙ Ø£Ù ÙØ¶Ù٠تعدÙÙØ§Øª ØºÙØ± Ù ÙØªÙÙØ© ÙÙØ£ÙØ¨Ø¬ÙØª)Ø ÙØ¥Ø°Ø§ ÙÙ ÙØ§ Ø¨ØªÙ Ø±ÙØ± Ø£ÙØ¨Ø¬Ùت ØºÙØ± Ù ØØ§Ø· ÙØ£ÙØ¨Ø¬ÙØªØ ÙØ¥ÙÙ ÙÙ Ù٠أ٠ÙÙÙÙ ÙÙØ§Ù ÙØªØ§Ø¦Ø¬ ØºÙØ± ٠تÙÙØ¹Ù.
ÙÙØ°ÙÙ ÙØ¥Ù برÙÙØ³Ù ÙÙØ°Ø§ ÙØ§ ÙØ¬Ø¨ Ø£Ù ÙØªÙ استخدا٠٠ÙÙ ÙÙ Ù ÙØ§Ù.
Ù
ØØ±Ùات Ø¬Ø§ÙØ§ Ø³ÙØ±Ùبت Ø§ÙØØ¯ÙØ«Ø© تدعÙ
Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØ®Ø§ØµØ© (private properties) Ù٠اÙÙÙØ§Ø³Ø Ù
سبÙÙØ© Ø¨Ø§ÙØ¹ÙاÙ
Ø© #, تÙ
شرØÙÙ
Ù٠اÙÙ
ÙØ§Ù Ø§ÙØ®Ùاص ÙØ§ÙØ¯ÙØ§Ù اÙÙ `private` ٠اÙÙ `protected`. ÙØ§ ÙØØªØ§Ø¬ Ø¥Ù٠برÙÙØ³Ù.
خصائص ÙÙØ°Ù ÙÙØ§ ٠شاÙÙÙØ§ Ø§ÙØ®Ø§ØµØ©. ØªØØ¯ÙØ¯ÙØ§Ø ÙØ§ ÙÙ ÙÙ ØªÙØ§Ø±Ø«Ùا.
âIn rangeâ ٠ع اÙtrap âhasâ
ÙÙØ§ ÙØ±Ù Ø£Ù Ø«ÙØ© أخرÙ.
ÙØ¯ÙÙØ§ Ø§ÙØ£ÙØ¨Ø¬ÙØª range:
let range = {
start: 1,
end: 10,
};
ÙÙØ¯ Ø£Ù ÙØ³ØªØ¹Ù
Ù in ÙÙØªØÙÙ Ù
Ù ÙØ¬Ùد ÙØ°Ø§ Ø§ÙØ±ÙÙ
Ù٠اÙÙrange.
اÙtrap has Ø§ÙØ°Ù ÙØ¹ØªØ±Ø¶ اسدعاء in.
has(target, property)
targetâ ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¯ÙØ ÙØªÙ ØªÙ Ø±ÙØ±Ù ÙÙ ØªØºÙØ± Ø£ÙÙ ÙÙnew Proxy,propertyâ Ø§Ø³Ù Ø§ÙØ®Ø§ØµÙØ©
ÙÙØ§ Ø§ÙØªØ·Ø¨ÙÙ:
let range = {
start: 1,
end: 10
};
range = new Proxy(range, {
has(target, prop) {
return prop >= target.start && prop <= target.end;
}
});
alert(5 in range); // true
alert(50 in range); // false
Ù ØµØ·ÙØ بدÙÙ ÙØ·ÙÙØ Ø£ÙÙØ³ ÙØ°ÙÙØ ÙØ³Ù٠تطبÙÙÙ.
Ø§ÙØ¯Ùا٠اÙÙ ÙØØ§Ø·Ø©: "apply"
ÙÙ ÙÙ Ø£Ù ÙØÙØ· Ø¯Ø§ÙØ© ببرÙÙØ³Ù Ø£ÙØ¶Ùا.
اÙtrap apply(target, thisArg, args) ÙØªØ¹Ø§Ù
Ù Ù
ع استدعاء Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØ¯Ø§ÙØ©:
targetÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¯Ù (Ø§ÙØ¯Ùا٠٠اÙÙ Ø¥ÙØ§ Ø£ÙØ¨Ø¬Ùت ÙÙ Ø¬Ø§ÙØ§ Ø³ÙØ±ÙبتthisArgÙÙ ÙÙÙ Ø©this.argsÙÙ ÙØ§Ø¦Ù Ø© ٠٠اÙÙ ØªØºÙØ±Ø§Øª.
عÙ٠سبÙ٠اÙÙ
ثا٠ÙÙØ§ ÙØ¹Ùد Ø§Ø³ØªØ°ÙØ§Ø± delay(f, ms)Ø ÙØ§Ùت٠ÙÙ
ÙØ§ Ø¨Ø¥ÙØ´Ø§Ø¦Ùا Ù٠اÙÙ
ÙØ§Ù اÙÙ
Ø²Ø®Ø±ÙØ§Øª decoratorsâ ÙØ§ÙتÙ
Ø±ÙØ± forwarding: Ø§ÙØªØ§Ø¨Ø¹Ø§Ù call Ùapply.
ÙÙ ÙØ°Ø§ اÙÙ
ÙØ§Ù Ø£ÙØ´Ø£ÙØ§ÙØ§ بدÙ٠برÙÙØ³Ù. ÙØ¥Ù استدعاء delay(f, ms) ÙØ§Ù
بإرجاع Ø¯Ø§ÙØ© تÙÙØ¶ ÙÙ Ø§ÙØ¥Ø³ØªØ¯Ø¹Ø§Ø¡Ø§Øª Ø¥ÙÙ f بعد ms Ù
ÙÙ٠ثاÙÙÙ.
ÙÙØ§ اÙÙÙØ¯ Ø§ÙØ³Ø§Ø¨ÙØ Ù Ù ØºÙØ± برÙÙØ³Ù:
function delay(f, ms) {
// ØªÙØ±Ø¬Ø¹ ØºÙØ§Ù ÙÙÙÙ
بتÙ
Ø±ÙØ± Ø§ÙØ§Ø³ØªØ¯Ø¹Ø§Ø¡ ﻹÙÙ f بعد Ø§ÙØªÙاء اÙÙÙØª
return function () {
// (*)
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(user) {
alert(`Hello, ${user}!`);
}
// بعد ÙØ°Ù Ø§ÙØ¥ØØ§Ø·Ù ÙØ¥Ù استدعاء Ø§ÙØ¯Ø§ÙØ© Ø³ÙØªØ£Ø®Ø± Ù 3 Ø«ÙØ§ÙÙ
sayHi = delay(sayHi, 3000);
sayHi('John'); // Hello, John! (after 3 seconds)
ÙØ°Ø§ ÙØ¹Ù
Ù ÙÙ
ا رأÙÙØ§ باÙÙØ¹Ù. Ø§ÙØ¯Ø§ÙØ© اÙÙ
ÙØÙØ·Ø© (*) تÙÙÙ
Ø¨Ø§ÙØ¥Ø³ØªØ¯Ø¹Ø§Ø¡ بعد Ø§ÙØªÙاء اÙÙÙØª.
ÙÙÙÙ ÙØ§ تÙÙÙ
Ø§ÙØ¯Ø§ÙØ© اÙÙ
ØÙط٠بتÙ
Ø±ÙØ± ÙØ±Ø§Ø¡Ø© أ٠تعدÙÙ Ø®Ø§ØµÙØ© Ø£Ù Ø£Ù Ø´ÙØ¡ آخر. بعد Ø§ÙØ¥ØØ§Ø·ÙØ ØªØªÙ
خسارة اÙÙØµÙ٠إÙÙ Ø§ÙØ®Ø§ØµØ§Ø¦Øµ Ø§ÙØ®Ø§ØµØ© Ø¨Ø§ÙØ¯Ø§ÙØ© Ø§ÙØ£ØµÙÙÙØ Ù
ث٠name, length ÙØºÙرÙÙ
:
function delay(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(user) {
alert(`Hello, ${user}!`);
}
alert(sayHi.length); // 1 (function length is the arguments count in its declaration)
sayHi = delay(sayHi, 3000);
alert(sayHi.length); // 0 (in the wrapper declaration, there are zero arguments)
إ٠ا٠Proxy Ø£ÙÙÙ Ø¨ÙØ«Ùر ÙØ£ÙÙ ÙÙÙÙ
بتÙ
Ø±ÙØ± ÙÙ Ø´ÙØ¦ Ø¥ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ
Ø³ØªÙØ¯Ù.
ÙÙØ§ ÙØ³ØªØ®Ø¯Ù برÙÙØ³Ù بÙÙØ§ Ù Ù Ø§ÙØ¯Ø§ÙØ© اÙÙ ØÙطة:
function delay(f, ms) {
return new Proxy(f, {
apply(target, thisArg, args) {
setTimeout(() => target.apply(thisArg, args), ms);
}
});
}
function sayHi(user) {
alert(`Hello, ${user}!`);
}
sayHi = delay(sayHi, 3000);
alert(sayHi.length); // 1 (*) proxy forwards "get length" operation to the target
sayHi("John"); // Hello, John! (after 3 seconds)
اÙÙØªÙجة Ù
Ù
اثÙÙØ ÙÙÙÙ Ø§ÙØ¢Ù ÙÙØ³Øª Ø§ÙØ§Ø³ØªØ¯Ø¹Ø§Ø¡Ø§Øª ÙÙØ· Ù
Ø§ÙØªÙ
تÙ
Ø±ÙØ±Ùا ÙÙÙ٠اÙÙÙ Ø§ÙØ¹Ù
ÙÙØ§Øª Ø£ÙØ¶Ùا. ÙÙØ°ÙÙ ÙØ¥Ù sayHi.length ÙØªÙ
Ø§Ø³ØªØ±Ø¬Ø§Ø¹ÙØ§ بشÙ٠صØÙØ Ø¨Ø¹Ø¯ Ø§ÙØ¥ØØ§Ø·Ù ÙÙ Ø§ÙØ³Ø·Ø± (*).
ÙØ¯ÙÙØ§ ØºÙØ§Ù Ø£ÙÙÙ.
ÙÙØ§Ù traps أخرÙ: اÙÙØ§Ø¦Ù Ø© اÙÙØ§Ù ÙØ© Ù ÙØ¬Ùدة ÙÙ Ø¨Ø¯Ø§ÙØ© اÙÙ ÙØ§Ù. ÙØ·Ø±ÙÙØ© استخدا٠ÙÙ Ù Ø´Ø§Ø¨ÙØ© Ù٠ا سبÙ.
Ø§ÙØ£ÙØ¨Ø¬ÙØª Reflect
Ø§ÙØ£ÙØ¨Ø¬ÙØª Reflect ÙÙ Ø£ÙØ¨Ø¬Ùت Ù
ÙØ¬Ùد Ù٠اÙÙØºØ© ÙØ§Ùذ٠ÙÙÙÙ
Ø¨ØªØ¨Ø³ÙØ· Ø¥ÙØ´Ø§Ø¡ Proxy.
ÙÙØ¯ ÙÙ٠سابÙÙØ§ Ø£Ù Ø§ÙØ¯ÙØ§Ù Ø§ÙØ¶Ù
ÙÙØ© Ù
ث٠[[Get]], [[Set]] ÙØºÙرÙÙ
ÙÙ
Ø¯ÙØ§Ù Ù
ØµØ¯Ø±ÙØ© ÙÙØ·Ø ÙØ§ ÙÙ
Ù٠استدعاؤÙÙ
بشÙÙ Ù
باشر.
اÙÙØ§Ø¦Ù Reflect ÙØ¬Ø¹Ù ذÙÙ Ø¨Ø³ÙØ·Ø§ ÙÙØ¹Ø§ Ù
ا. Ø§ÙØ¯ÙØ§Ù Ø§ÙØ®Ø§ØµØ© ب٠ÙÙ ØºÙØ§Ù Ù
باشر ÙÙØ¯ÙØ§Ù Ø§ÙØ¶Ù
ÙÙØ©.
ÙÙØ§ Ø£Ù
Ø«ÙØ© ÙØ¨Ø¹Ø¶ Ø§ÙØ¹Ù
ÙÙØ§Øª ÙÙØ°Ù٠استدعاءات ا٠Reflect ÙØ§Ùت٠تÙÙÙ
بعÙ
Ù ÙÙØ³ Ø§ÙØ´Ùئ:
| Operation | Reflect call |
Internal method |
|---|---|---|
obj[prop] |
Reflect.get(obj, prop) |
[[Get]] |
obj[prop] = value |
Reflect.set(obj, prop, value) |
[[Set]] |
delete obj[prop] |
Reflect.deleteProperty(obj, prop) |
[[Delete]] |
new F(value) |
Reflect.construct(F, value) |
[[Construct]] |
| ⦠| ⦠| ⦠|
عÙ٠سبÙ٠اÙ٠ثاÙ:
let user = {};
Reflect.set(user, 'name', 'John');
alert(user.name); // John
Ø¨Ø§ÙØªØØ¯ÙØ¯Ø ÙØ³Ù
Ø ÙÙØ§ اÙReflect باستدعاء Ø§ÙØ¹Ù
ÙÙØ§Øª (new, deleteâ¦) ÙØ¯Ùا٠(Reflect.construct, Reflect.deleteProperty, â¦). ÙÙØ°Ù Ù
ÙØ²Ø© Ø¬ÙØ¯Ø© ÙÙ
Ø«ÙØ±Ø©Ø ÙÙÙÙ ÙÙØ§ Ø´ÙØ¦ آخر Ù
ÙÙ
.
ÙÙÙ Ø®Ø§ØµÙØ© ضÙ
ÙÙØ©Ø تÙ
Ø§Ø¹ØªØ±Ø§Ø¶ÙØ§ ببرÙÙØ³ÙØ Ø¯Ø§ÙØ© Ù٠ا٠ReflectØ Ø¨ÙÙØ³ Ø§ÙØ¥Ø³Ù
ÙØ§ÙÙ
ØªØºÙØ±Ø§Øª Ø§ÙØ®Ø§ØµØ© باÙtrap.
ÙØ°ÙÙ ÙÙ
ÙÙÙØ§ استخداÙ
Reflect ÙØªÙ
Ø±ÙØ± عÙ
ÙÙØ© Ø¥Ù٠اÙÙØ§Ø¦Ù Ø§ÙØ£ØµÙÙ.
ÙÙ ÙØ°Ø§ اÙÙ
Ø«Ø§ÙØ ÙÙØ§ Ù
Ù get Ù set ÙÙÙÙ
ا٠بتÙ
Ø±ÙØ± اÙÙØ±Ø§Ø¡Ø© ÙØ§ÙتعدÙ٠إÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª بشÙÙ Ø´ÙØ§ÙØ ÙÙØ¸ÙØ±Ø§Ù Ø±Ø³Ø§ÙØ©:
let user = {
name: "John",
};
user = new Proxy(user, {
get(target, prop, receiver) {
alert(`GET ${prop}`);
return Reflect.get(target, prop, receiver); // (1)
},
set(target, prop, val, receiver) {
alert(`SET ${prop}=${val}`);
return Reflect.set(target, prop, val, receiver); // (2)
}
});
let name = user.name; // shows "GET name"
user.name = "Pete"; // shows "SET name=Pete"
ÙÙØ§:
Reflect.getØªÙØ±Ø£ Ø®Ø§ØµÙØ© ÙØ£ÙØ¨Ø¬ÙØª.Reflect.setتÙÙ٠بتعدÙÙ Ø®Ø§ØµÙØ© ÙØ£Ùبجت ÙØªÙرجعtrueÙÙ ØØ§ÙØ© اÙÙØ¬Ø§Ø ÙfalseÙÙ ØºÙØ± ذÙÙ.
ÙÙÙØ°Ø§ ÙÙ Ø´ÙØ¦ Ø¨Ø³ÙØ·: إذا أراد trap Ø£Ù ÙÙ
رر Ø§Ø³ØªØ¯Ø¹Ø§Ø¡ÙØ§ ÙØ£ÙØ¨Ø¬ÙØª ÙØ¥ÙÙ Ù
٠اÙÙØ§Ù٠استدعاء Reflect.<method> بÙÙØ³ Ø§ÙØ®ØµØ§Ø¦Øµ.
ÙÙ Ø£ØºÙØ¨ Ø§ÙØØ§ÙØ§Øª ÙÙ
ÙÙÙØ§ ÙØ¹Ù ÙÙØ³ Ø§ÙØ´Ùئ بدÙÙ ReflectØ Ø¹Ù٠سبÙ٠اÙÙ
Ø«Ø§ÙØ ÙØ±Ø§Ø¡Ø© Ø®Ø§ØµÙØ© ب٠Reflect.get(target, prop, receiver) ÙÙ
Ù٠استبداÙ٠ب٠target[prop]. ÙÙÙÙ Ù
ع ذÙÙ ÙÙØ§Ù ÙØ±ÙÙ Ù
ÙÙ
Ù.
Ø¥ØØ§Ø·Ø© اÙÙgetter Ø£Ù Ø§ÙØ¬Ø§Ùب ببرÙÙØ³Ù
ÙÙØ§ ÙØ±Ù Ù
ثاÙÙØ§ ÙÙØ¶Ø ÙÙ
اذا Reflect.get Ø£ÙØ¶Ù. ÙØ³ÙØ±Ù Ø£ÙØ¶Ùا ÙÙ
اذا get/set ÙØ¯ÙÙÙ
اÙÙ
ØªØºÙØ± Ø§ÙØ±Ø§Ø¨Ø¹ receiver Ø§ÙØ°Ù ÙÙ
ÙØ³ØªØ®Ø¯Ù
Ù Ù
Ù ÙÙÙ.
ÙØ¯ÙÙØ§ Ø§ÙØ£ÙØ¨Ø¬ÙØª user Ø§ÙØ°Ù ÙØØªÙ٠عÙÙ Ø§ÙØ®Ø§ØµÙØ© _name ÙØ¬Ø§Ùب ÙÙØ§.
ÙÙØ§ برÙÙØ³Ù ØÙÙÙØ§:
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) {
return target[prop];
}
});
alert(userProxy.name); // Guest
اÙtrap get Ø´ÙØ§Ù ÙÙØ§Ø ØÙØ« تÙÙÙ
بإرجاع Ø§ÙØ®Ø§ØµÙØ© Ø§ÙØ£ØµÙÙØ© ÙÙØ§ ØªÙØ¹Ù Ø£Ù Ø´ÙØ¦ آخر. ÙÙØ°Ø§ طاÙÙ ÙÙ
ثاÙÙØ§.
ÙÙ Ø´ÙØ¦ ÙØ¨Ø¯Ù ÙØ£Ù٠صØÙØ. ÙÙÙÙ ÙÙØ§ ÙÙØ´Ø¦ ٠ثاÙÙØ§ Ø£ÙØ«Ø± تعÙÙØ¯Ùا.
بعد ÙØ±Ø§Ø«Ø© Ø£ÙØ¨Ø¬Ùت آخر admin Ù
Ù userØ ÙÙ
ÙÙÙØ§ Ù
Ø´Ø§ÙØ¯Ø© Ø§ÙØ³ÙÙÙ Ø§ÙØ®Ø§Ø·Ø¦:
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) {
return target[prop]; // (*) target = user
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
// Expected: Admin
alert(admin.name); // outputs: Guest (?!?)
استرجاع admin.name ÙØ¬Ø¨ Ø£Ù ÙÙØªØ¬ âAdminâ, ÙÙÙØ³"Guest"`!
٠اذا ØØ¯Ø«Ø ٠٠اÙÙ Ù Ù٠أÙÙØ§ ÙØ¹ÙÙØ§ Ø´ÙØ¦Ùا Ø®Ø§Ø·Ø¦ÙØ§ ٠ع اÙÙØ±Ø§Ø«Ø©Ø
ÙÙÙ٠إذا ÙÙ ÙØ§ Ø¨Ø¥Ø²Ø§ÙØ© Ø§ÙØ¨Ø±ÙÙØ³ÙØ Ø³ÙØ¹Ù Ù ÙÙ Ø´ÙØ¦ Ù٠ا Ù٠٠تÙÙØ¹.
اÙÙ
Ø´ÙÙØ© ØªØØ¯ÙØ¯ÙØ§ ÙÙ Ø§ÙØ¨Ø±ÙÙØ³Ù ÙÙ Ø§ÙØ³Ø·Ø± (*).
-
Ø¹ÙØ¯ ÙØ±Ø§Ø¡Ø©
admin.nameÙØ¥Ù Ø§ÙØ£ÙØ¨Ø¬ÙØªadminÙÙØ³ ÙØ¯ÙÙ Ø®Ø§ØµÙØ© ÙÙØ°Ù ÙÙØ°Ùب Ø§ÙØ¨ØØ« Ø¥Ù٠اÙÙprototype اÙ٠تص٠بÙ. -
اÙprototype ÙÙ
userProxy. -
Ø¹ÙØ¯ ÙØ±Ø§Ø¡Ø© Ø§ÙØ®Ø§ØµÙØ©
nameÙ Ù Ø§ÙØ¨Ø±ÙÙØ³ÙØ ÙØ¥Ù اÙtrapgetÙÙØ´ØºÙ ÙÙÙØ±Ø¬Ø¹ ÙÙÙ ØªÙØ§ Ù Ù Ø§ÙØ£ÙØ¨Ø¬ÙØª Ø£ÙØ£ØµÙÙ Ù٠اtarget[prop]ÙÙ Ø§ÙØ³Ø·Ø±(*).استدعاء
target[prop]Ø Ø¹ÙØ¯Ù ا تÙÙÙpropØ¬Ø§ÙØ¨Ø©Ø تÙÙ٠بتشغÙ٠اÙÙÙØ¯ ÙÙ Ø³ÙØ§Ùthis=target. ÙØ°Ù٠تÙÙ٠اÙÙØªÙجةthis._name٠٠اÙÙØ§Ø¦Ù Ø§ÙØ£ØµÙÙtargetÙØ§Ùذ٠ÙÙuser.
ÙØ¥ØµÙØ§Ø Ø°ÙÙØ ÙØØªØ§Ø¬ Ø¥ÙÙ receiverØ Ø§ÙÙ
ØªØºÙØ± Ø§ÙØ«Ø§ÙØ« ÙÙtrap get. ÙÙ ØªØØ§Ùظ عÙ٠اÙÙÙÙ
Ø© Ø§ÙØµØÙØØ© ÙÙ this ÙØªÙ
Ø±ÙØ±Ùا ÙØ¬Ø§Ùب. ÙÙ ØØ§ÙØªÙØ§ ÙÙ admin.
ÙÙ٠تÙ
رر Ø³ÙØ§Ù ÙØ¬Ø§ÙØ¨Ø ÙÙ Ø§ÙØ¯ÙØ§Ù Ø§ÙØ¹Ø§Ø¯ÙØ© ÙÙ
ÙÙÙØ§ استخداÙ
call/apply ÙÙÙÙ ÙØ°Ø§ Ø¬Ø§ÙØ¨ ÙÙØ§ ÙØªÙ
Ø§Ø³ØªØ¯Ø¹Ø§Ø¤ÙØ ÙÙØ· اÙÙØµÙ٠إÙÙ٠إÙÙÙ.
ØªØ³ØªØ·ÙØ¹ Reflect.get Ø£Ù ØªÙØ¹Ù ذÙÙ. ÙÙ Ø´ÙØ¦ ÙÙ
ÙÙÙ Ø£Ù ÙØ¹Ù
٠بشÙ٠صØÙØ Ø¥Ø°Ø§ استخدÙ
ÙØ§Ù.
ÙÙØ§ اÙÙÙØ¯ اÙÙ ØµØØ:
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) { // receiver = admin
return Reflect.get(target, prop, receiver); // (*)
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
alert(admin.name); // Admin
ÙØ§ÙØ¢Ù ÙØ¥Ù receiver Ø§ÙØ°Ù ÙØØ§ÙØ¸ عÙ٠اÙÙÙÙ
Ø© Ø§ÙØµØÙØÙ thisØ ÙØªÙ
تÙ
Ø±ÙØ±Ù ÙÙØ¬Ø§Ùب باستخداÙ
Reflect.get ÙÙ Ø§ÙØ³Ø·Ø± (*).
ÙÙ ÙÙÙØ§ ÙØªØ§Ø¨Ø© اÙtrap بشÙÙ Ø£ÙØµØ±:
get(target, prop, receiver) {
return Reflect.get(...arguments);
}
استدعاءات Reflect Ù
سÙ
اة بÙÙØ³ أسÙ
اء اÙtraps ÙØªØ³ØªÙب٠ÙÙØ³ اÙÙ
ØªØºÙØ±Ø§Øª. تÙ
Ø¥ÙØ´Ø§Ø¦ÙÙ
Ø¨ÙØ°Ù Ø§ÙØ·Ø±ÙÙØ©.
ÙØ°ÙÙ ÙØ¥Ù return Reflect... ÙØ¹Ø·ÙÙØ§ طرÙÙØ© Ø¢Ù
ÙÙ ÙØªÙ
Ø±ÙØ± Ø§ÙØ¹Ù
ÙÙØ§Øª دÙ٠أ٠ÙÙÙ٠إ٠ÙÙØ§ ÙØ³ÙÙØ§ Ø´ÙØ¦Ùا.
ØØ¯Ùد Ø§ÙØ¨Ø±ÙÙØ³Ù
Ø¥Ù Ø§ÙØ¨Ø±ÙÙØ³Ù Ù٠طرÙÙØ© ÙØ±Ùدة ÙØªØ¹Ø¯Ù٠سÙÙ٠اÙÙØ§Ø¦Ùات اÙÙ ÙØ¬Ùدة عÙ٠أدÙ٠٠ستÙÙ. Ù٠ع ذÙÙ ÙÙ ÙÙØ³ Ø£ÙØ¶Ù Ø´ÙØ¦. ÙÙØ§Ù ØØ¯Ùد.
Ø§ÙØ£ÙØ¨Ø¬ÙØªØ³ اÙÙ ÙØ¬Ùد باÙÙØ¹Ù: Internal slots
اÙÙØ«Ùر Ù
٠اÙÙØ§Ø¦Ùات اÙÙ
ÙØ¬Ùدة باÙÙØ¹Ù Ù
ث٠Map, Set, Date, Promise ÙØºÙرÙÙ
ÙØ³ØªØ®Ø¯Ù
ÙÙ Ù
Ø§ÙØ³Ù
Ù âinternal slotsâ.
Ù٠عبارة Ø¹Ù Ø®ØµØ§Ø¦ØµØ ÙÙÙÙ Ù
ØÙÙØ¸Ø© ÙÙØªÙ
استخداÙ
ÙØ§ ضÙ
ÙÙÙØ§ ÙÙØ·. عÙ٠سبÙ٠اÙÙ
Ø«Ø§ÙØ ÙØ®Ø²Ù اÙÙ Map Ø§ÙØ¹Ùاصر ÙÙ ÙØªØØ© داخÙÙØ© (internal slot) تسÙ
Ù [[MapData]]. Ø§ÙØ¯Ùا٠اÙÙ
ÙØ¬Ùدة Ù٠اÙÙØºØ© تص٠إÙÙÙÙ
Ù
باشرة ÙÙÙØ³ ع٠طرÙÙ [[Get]]/[[Set]]. ÙÙØ°ÙÙ ÙØ¥Ù Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØ§ ÙØ³ØªØ·Ùع اعتراضÙÙ
.
Ù٠اذا ÙÙØªÙ Ø Ø¥ÙÙÙ Ø£Ø´ÙØ§Ø¡ Ù Ø¶Ù ÙØ© عÙÙ ÙÙ Ø§ÙØ£ØÙاÙ!
ØØ³ÙÙØ§Ø ÙÙØ§ اÙÙ Ø´ÙÙÙØ بعد Ø£Ù ÙØªÙ Ø¥ØØ§Ø·Ø© Ø£ÙØ¨Ø¬Ùت ÙÙØ°Ø§ ببرÙÙØ³Ù ÙØ¥Ù Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØ§ ÙÙ ÙÙ ÙØ°Ù اÙÙ internal slots ÙÙØ°ÙÙ ÙØ¥Ù Ø§ÙØ¯ÙØ§Ù Ø§ÙØ¶Ù ÙÙØ© Ø³ØªÙØ´Ù.
عÙ٠سبÙ٠اÙ٠ثاÙ:
let map = new Map();
let proxy = new Proxy(map, {});
proxy.set('test', 1); // خطأ
ضÙ
ÙÙÙØ§Ø ÙØ®Ø²Ù اÙÙ Map ÙÙ Ø§ÙØ¨ÙØ§ÙØ§Øª ÙÙ [[MapData]]. ÙØ§ÙبرÙÙØ³Ù ÙÙØ³ ÙØ¯ÙÙ ÙØªØØ© (slot) ÙÙØ°Ù. ÙØ§ÙØ¯Ø§ÙØ© Map.prototype.set ØªØØ§Ù٠أ٠تص٠إÙÙ Ø§ÙØ®Ø§ØµÙØ© Ø§ÙØ¯Ø§Ø®ÙÙØ© this.[[MapData]] ÙÙÙ٠بÙ
ا Ø£Ù this=proxy ÙØ¥ÙÙØ§ ÙØ§ ØªØ¬Ø¯ÙØ§ Ø¨Ø¯Ø§Ø®Ù Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØªÙØ´Ù.
ÙØØ³Ù Ø§ÙØØ¸Ø ÙÙØ§Ù طرÙÙØ© ÙØ¥ØµÙØ§Ø Ø°ÙÙ:
let map = new Map();
let proxy = new Proxy(map, {
get(target, prop, receiver) {
let value = Reflect.get(...arguments);
return typeof value == 'function' ? value.bind(target) : value;
}
});
proxy.set('test', 1);
alert(proxy.get('test')); // 1 (works!)
ÙØ§ÙØ¢Ù Ù٠تعÙ
Ù Ø¬ÙØ¯ÙØ§Ø ÙØ£Ù اÙtrap get ÙØ±Ø¨Ø· خصائص Ø§ÙØ¯Ø§ÙØ© Ø Ù
ث٠map.setØ Ø¨Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ
Ø³ØªÙØ¯Ù.
عÙÙ Ø¹ÙØ³ اÙÙ
Ø«Ø§Ù Ø§ÙØ³Ø§Ø¨ÙØ ÙØ¥Ù ÙÙÙ
Ø© this بداخ٠proxy.set(...) Ù٠تÙÙ٠برÙÙØ³Ù ÙÙÙÙ ÙÙØ· اÙmap Ø§ÙØ£ØµÙÙ. ÙØ°ÙÙ Ø¹ÙØ¯Ù
ا ØªØØ§ÙÙ Ø§ÙØ¯Ø§ÙØ© set أ٠تص٠إÙÙ this.[[MapData]] ÙØ¥ÙÙØ§ ØªÙØ¬Ø.
ArrayÙØ§ ØªØØªÙ٠عÙÙ internal slotsÙØ°ÙÙ ÙØ§ ØªÙØ¬Ø¯ Ù Ø´ÙÙØ© ÙÙØ°Ù Ø¹ÙØ¯ Ø¥ØØ§Ø·Ø© اÙ٠صÙÙÙØ© ببرÙÙØ³Ù.
Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØ®Ø§ØµØ© Private fields
A similar thing happens with private class fields.
عÙ٠سبÙ٠اÙÙ
Ø«Ø§ÙØ Ø§ÙØ¯Ø§ÙØ© getName() تص٠إÙÙ Ø§ÙØ®Ø§ØµÙØ© Ø§ÙØ®Ø§ØµØ© #name ÙØªÙ٠بعد Ø§ÙØ¥ØØ§Ø·Ø©:
class User {
#name = "Guest";
getName() {
return this.#name;
}
}
let user = new User();
user = new Proxy(user, {});
alert(user.getName()); // خطأ
Ø§ÙØ³Ø¨Ø¨ Ù٠ذÙÙ Ø£Ù Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØ¯Ø§Ø®ÙÙØ© ÙØªÙ
Ø¥ÙØ´Ø§Ø¤Ùا باÙÙ internal slots. ÙÙØ§ تستخدÙ
Ø¬Ø§ÙØ§ Ø³ÙØ±Ùبت [[Get]]/[[Set]] Ø¹ÙØ¯ اÙÙØµÙ٠إÙÙÙÙ
.
Ø¹ÙØ¯ استدعاء getName() ÙØ¥Ù ÙÙÙ
Ø© this ÙØªÙ
Ø¥ØØ§Ø·ØªÙا Ø¨Ø§ÙØ£ÙØ¨Ø¬ÙØª userØ ÙÙÙ ÙØ§ تÙ
ÙÙ ÙØªØØ© (slot) Ù
ع Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØ®Ø§ØµØ©.
٠رة Ø£Ø®Ø±ÙØ ÙØ¥Ù Ø§ÙØÙ Ø¨Ø§ÙØ±Ø¨Ø· ÙØ¬Ø¹ÙÙØ§ تع٠Ù:
class User {
#name = 'Guest';
getName() {
return this.#name;
}
}
let user = new User();
user = new Proxy(user, {
get(target, prop, receiver) {
let value = Reflect.get(...arguments);
return typeof value == 'function' ? value.bind(target) : value;
},
});
alert(user.getName()); // Guest
Ù٠ا ÙÙÙØ ÙØ¥Ù Ø§ÙØÙ Ù٠عÙÙØ¨Ø Ù٠ا ØªÙ Ø§ÙØªÙØ¶ÙØ سابÙÙØ§: ÙØ¥ÙÙ ÙÙÙÙ Ø¨ØªØ¹Ø±ÙØ¶ اÙÙØ§Ø¦Ù Ø§ÙØ£ØµÙÙ ÙÙØ¯Ø§ÙØ© ÙÙØ³Ù Ø Ø¨ØªÙ Ø±ÙØ±Ù ÙØ¥ÙÙØ§Ø¡ اÙÙØ§Ø¦Ùات برÙÙØ³Ù Ø§ÙØ£Ø®Ø±Ù.
Ø§ÙØ¨Ø±ÙÙØ³Ù ÙÙØ³ ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ Ø³ØªÙØ¯Ù
Ø¥Ù Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØ§ÙÙØ§Ø¦Ù Ø§ÙØ£ØµÙ٠٠ختÙÙØ§Ù. ÙØ°Ø§ Ø·Ø¨ÙØ¹ÙØ ØµØÙØØ
ÙØ°Ù٠إذا Ø§Ø³ØªØ®Ø¯Ù ÙØ§ Ø§ÙØ£ÙØ¨Ø¯Ø¬ÙØª Ø§ÙØ£ØµÙÙ ÙØ®Ø§ØµÙØ©Ø Ø«Ù Ø¥ØØ§Ø·ØªÙ ببرÙÙØ³ÙØ ÙØ¥Ù Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØ§ ÙÙ ÙÙ Ø¥ÙØ¬Ø§Ø¯Ù:
let allUsers = new Set();
class User {
constructor(name) {
this.name = name;
allUsers.add(this);
}
}
let user = new User("John");
alert(allUsers.has(user)); // true
user = new Proxy(user, {});
alert(allUsers.has(user)); // false
ÙÙ
ا ÙØ±ÙØ ÙØ¥Ù٠بعد Ø§ÙØ¥ØØ§Ø·Ø© ÙØ§ ÙØ³ØªØ·Ùع Ø£Ù ÙØ¬Ø¯ user Ù٠اÙÙ
جÙ
ÙØ¹Ù allUsersØ ÙØ£Ù Ø§ÙØ¨Ø±ÙÙØ³Ù ÙÙ ÙØ§Ø¦Ù Ù
ختÙÙ.
===ÙÙÙÙ ÙÙØ³Øª ÙÙØ§Ù طرÙÙØ© ÙØ§Ø¹ØªØ±Ø§Ø¶ اختبار اÙÙ
Ø³Ø§ÙØ§Ø© === ÙÙØ£ÙØ¨Ø¬ÙØªØ³. ÙØ¥Ù Ø§ÙØ£ÙØ¨Ø¬ÙØª Ù
ساÙ٠تÙ
اÙ
ا ÙÙÙØ³Ù ÙÙØ· ÙÙÙØ³ Ø£Ù ÙÙÙ
Ø© أخرÙ.
ÙØ°ÙÙ ÙØ¥Ù ÙÙ Ø§ÙØ¹Ù ÙÙØ§Øª ÙØ§ÙÙÙØ§Ø³Ø² اÙ٠بÙÙÙ Ù٠اÙÙØºØ© ÙØ§ÙØªÙ ØªÙØ§Ø±Ù اÙÙØ§Ø¦Ùات ÙÙÙ Ø³Ø§ÙØ§Ø© ستÙÙÙ Ø¨Ø§ÙØªÙرÙ٠بÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª ÙØ§ÙبرÙÙØ³Ù. ÙØ§ ÙÙØ¬Ø¯ استبدا٠ÙÙØ§.
Ø§ÙØ¨Ø±ÙÙØ³Ù اÙÙØ§Ø¨Ù ÙÙØ¥Ùغاء
Ø¯Ø¹ÙØ§ ÙÙÙÙ Ø£Ù ÙØ¯ÙÙØ§ Ù ØµØ¯Ø±Ø ÙÙØ±Ùد Ø£Ù ÙÙ ÙØ¹ اÙÙØµÙ٠إÙÙÙ Ù٠أ٠ÙÙØª.
Ù Ø§ÙØ³ØªØ·Ùع ÙØ¹ÙÙ ÙÙ Ø£Ù ÙØÙØ·Ù ببرÙÙØ³Ù ÙØ§Ø¨Ù ÙÙØ¥ÙØºØ§Ø¡Ø Ø¨Ø¯Ù٠أ٠trap. ÙØ°Ø§ Ø§ÙØ¨Ø±ÙÙØ³Ù سÙÙÙÙ Ø¨ØªÙ Ø±ÙØ± Ø§ÙØ¹Ù ÙÙØ§Øª Ø¥ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª ÙÙÙ ÙÙÙØ§ Ø£Ù ÙÙ ÙØ¹ اÙÙØµÙ٠إÙÙÙ Ù٠أ٠ÙÙØª.
Ø§ÙØ´ÙÙ:
let {proxy, revoke} = Proxy.revocable(target, handler)
Ø§ÙØ¥Ø³ØªØ¯Ø¹Ø§Ø¡ ÙÙÙÙ
بإرجاع Ø£ÙØ¨Ø¬Ùت ÙØØªÙ٠عÙÙ proxy ÙØ¯Ø§ÙØ© revoke ÙØ¥Ø¨Ø·Ø§ÙÙ.
ÙØ§Ù ٠ثاÙÙØ§:
let object = {
data: 'Valuable data',
};
let { proxy, revoke } = Proxy.revocable(object, {});
// تÙ
Ø±ÙØ± اÙÙØ±ÙÙØ³Ù Ø¥ÙÙ Ù
ÙØ§Ù آخر بÙÙØ§ Ù
Ù Ø§ÙØ£ÙØ¨Ø¬ÙØª...
alert(proxy.data); // Ø¨ÙØ§Ùات ÙÙÙ
Ø©
// ÙÙÙ
ا بعد
revoke();
// ÙØ§ ÙØ¹Ù
Ù Ø§ÙØ¨Ø±ÙÙØ³Ù Ø§ÙØ¢Ù (تÙ
Ø§ÙØ¥Ùغاء)
alert(proxy.data); // خطأ
A call to revoke() removes all internal references to the target object from the proxy, so they are no longer connected.
Initially, revoke is separate from proxy, so that we can pass proxy around while leaving revoke in the current scope.
We can also bind revoke method to proxy by setting proxy.revoke = revoke.
Another option is to create a WeakMap that has proxy as the key and the corresponding revoke as the value, that allows to easily find revoke for a proxy:
let revokes = new WeakMap();
let object = {
data: "Valuable data"
};
let {proxy, revoke} = Proxy.revocable(object, {});
revokes.set(proxy, revoke);
// ..somewhere else in our code..
revoke = revokes.get(proxy);
revoke();
alert(proxy.data); // خطأ (تÙ
Ø¥ÙØºØ§Ø¤Ù)
We use WeakMap instead of Map here because it wonât block garbage collection. If a proxy object becomes âunreachableâ (e.g. no variable references it any more), WeakMap allows it to be wiped from memory together with its revoke that we wonât need any more.
اÙ٠راجع
اÙÙ ÙØ®Øµ
إ٠اÙÙ Proxy ÙÙ ØºÙØ§Ù ØÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØªØ ÙØ§Ùذ٠ÙÙÙÙ
بتÙ
Ø±ÙØ± Ø§ÙØ¹Ù
ÙÙØ§Øª Ø¥ÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØªØ ÙÙÙÙÙ
باعتراض بعضÙÙ
بشÙÙ Ø§Ø®ØªÙØ§Ø±Ù.
ÙÙ ÙÙÙ Ø£Ù ÙØÙØ· Ø£Ù Ø£ÙØ¨Ø¬ÙØªØ Ø¨Ù Ø§ ÙÙ٠اÙÙÙØ§Ø³ ÙØ§ÙØ¯Ø§ÙØ©.
Ø§ÙØ´ÙÙ:
let proxy = new Proxy(target, {
/* traps */
});
â¦Ø¨Ø¹Ø¯ ذÙÙ ÙØ¬Ø¨ Ø£Ù ÙØ³ØªØ®Ø¯Ù
proxy ÙÙ ÙÙ Ù
ÙØ§Ù بدÙÙØ§ Ù
Ù target. Ø¥Ù Ø§ÙØ¨Ø±ÙÙØ³Ù ÙØ§ ÙØØªÙ٠عÙ٠خصائص Ø£Ù Ø¯ÙØ§Ù خاصة بÙ. ÙÙ ÙÙÙÙ
باعتراض Ø§ÙØ¹Ù
ÙÙ٠إذا ÙØ¬Ø¯ trap ÙØ¥Ùا ÙØ¥ÙÙ ÙÙ
رر Ø§ÙØ¹Ù
ÙÙ٠إÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ
Ø³ØªÙØ¯Ù.
ÙÙ ÙÙÙØ§ Ø£Ù ÙØ¹ØªØ±Ø¶:
We can trap:
- Reading (
get), writing (set), deleting (deleteProperty) a property (even a non-existing one). - Calling a function (
applytrap). - The
newoperator (constructtrap). - Many other operations (the full list is at the beginning of the article and in the docs).
ÙØ°Ø§ ÙØ³Ù Ø ÙÙØ§ Ø£Ù ÙÙØ´Ø¦ Ø®ÙØ§Øµ ÙØ¯ÙØ§Ù Ø§ÙØªØ±Ø§Ø¶ÙØ© ÙØ§Ø³ØªØ±Ø¬Ø§Ø¹ ÙÙÙ Ø§ÙØªØ±Ø§Ø¶ÙØ© ÙØ£ÙØ¨Ø¬ÙØª Ù ÙØÙØ¸ ÙØ§ÙÙØ«Ùر.
ÙÙ ÙÙÙØ§ Ø£ÙØ¶Ùا Ø£Ù ÙØ¹ØªØ±Ø¶ Ø£ÙØ¨Ø¬Ùت ٠رات عدة ببرÙÙØ³Ù ٠ختÙÙØ ÙØªØ¹ÙÙÙ ÙØ§ بطر٠٠ختÙÙØ©.
The Reflect API is designed to complement Proxy. For any Proxy trap, thereâs a Reflect call with same arguments. We should use those to forward calls to target objects.
Ø§ÙØ¨Ø±ÙÙØ³Ù ÙÙ ØØ¯Ùد:
- Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙ٠بÙÙØ© باÙÙØ¹Ù ت٠تÙÙ âinternal slotsâØ ÙØ§ÙÙØµÙ٠إÙÙÙØ§ ÙØ§ Ù ÙÙÙ Ø¥ØØ§Ø·ØªÙ ببرÙÙØ³Ù. Ø£ÙØ¸Ø± Ø¥ÙÙ Ø§ÙØÙ Ø£Ø¹ÙØ§Ù.
- ÙÙ
Ø«ÙÙ Ø£ÙØ¶Ùا Ø§ÙØ®ØµØ§Ø¦Øµ Ø§ÙØ®Ø§ØµØ© Ù٠اÙÙÙØ§Ø³Ø ØÙØ« Ø£ÙÙÙ
ÙØªÙ
Ø¥ÙØ´Ø§Ø¤ÙÙ
داخÙÙØ§ باستخداÙ
ÙØªØØ§Øª (slots). ÙÙØ°ÙÙ ÙØ¥Ù Ø§ÙØ¯Ùا٠اÙÙ
غÙÙØ© ÙØ¬Ø¨ Ø£Ù ØªØØªÙ٠عÙÙ Ø§ÙØ£ÙØ¨Ø¬ÙØª اÙÙ
Ø³ØªÙØ¯Ù ÙÙÙÙ
Ø© ÙÙ
thisÙÙÙØµÙ٠إÙÙÙÙ Ø¨ÙØ¬Ø§Ø. - اختبار Ø§ÙØªØ³Ø§ÙÙ
===ÙØ§ ÙÙ Ù٠اعتراضÙ. - Ø§ÙØ³Ø±Ø¹Ø©: ÙØ°Ø§ ÙØ¹ØªÙ د عÙÙ Ø§ÙØ¥Ùج٠ÙÙÙ٠بشÙÙ Ø¹Ø§Ù ÙØ¥Ù اÙÙØµÙ٠إÙÙ Ø®Ø§ØµÙØ© Ø¨Ø¨Ø±ÙØ·Ø³Ù Ø¨Ø³ÙØ· ÙØ³ØªØºØ±Ù ÙÙØªÙا أطÙÙ.
Ø§ÙØªØ¹ÙÙÙØ§Øª
<code>Ø ÙÙÙÙØ«Ùر Ù Ù Ø§ÙØ³Ø·Ùر استخدÙ<pre>Ø ÙÙØ£Ùثر Ù Ù 10 Ø³Ø·ÙØ± استخد٠(plnkr, JSBin, codepenâ¦)