Proxy ãªããžã§ã¯ãã¯å¥ã®ãªããžã§ã¯ããã©ããããããããã£ããã®ä»ã®èªã¿åã/æžã蟌ã¿ãªã©ã®æäœãã€ã³ã¿ãŒã»ããããŸããå¿
èŠã«å¿ããŠããããç¬èªã«åŠçãããããªããžã§ã¯ããééçã«ããããåŠçã§ããããã«ããŸãã
Proxy ã¯å€ãã®ã©ã€ãã©ãªãäžéšã®ãã©ãŠã¶ãã¬ãŒã ã¯ãŒã¯ã§äœ¿ãããŠããŸãããã®ç« ã§ã¯ãå€ãã®å®è·µçãªã¢ããªã±ãŒã·ã§ã³ã玹ä»ããŸãã
Proxy
æ§æ:
let proxy = new Proxy(target, handler)
targetâ ã©ãããããªããžã§ã¯ãã§ãã颿°å«ãäœã§ãOKã§ããhandlerâ ãããã·èšå®: æäœãã€ã³ã¿ãŒã»ããããã¡ãœããã§ãã âãã©ããâ ããã€ãªããžã§ã¯ãã§ããäŸ:getãã©ããã¯targetã®ããããã£ã®èªã¿åãçšãsetãã©ããã¯ãtargetãžã®ããããã£æžã蟌ã¿çšããªã©ã
proxy ã®æäœã§ã¯ãhandler ã«å¯Ÿå¿ãããã©ãããããå Žåã¯ãããå®è¡ãããŸãããã以å€ã®å Žåã¯ãæäœã¯ target ã§å®è¡ãããŸãã
æåã®äŸãšããŠããã©ãããªãã§ãããã·ãäœã£ãŠã¿ãŸãããã:
let target = {};
let proxy = new Proxy(target, {}); // 空ã®ãã³ãã©
proxy.test = 5; // ãããã·ãžã®æžã蟌㿠(1)
alert(target.test); // 5, ããããã£ã target ã§çŸããŸãã!
alert(proxy.test); // 5, proxy ããã®èªã¿åãããšãã§ããŸã (2)
for(let key in proxy) alert(key); // test, ã€ãã¬ãŒã·ã§ã³ãæ©èœããŸã (3)
ãã©ããããªãã®ã§ãproxy äžã®ãã¹ãŠã®æäœã¯ target ã«è»¢éãããŸãã
- æžãèŸŒã¿æäœ
proxy.test=ã¯targetã«å€ãèšå®ããŸãã - èªã¿èŸŒã¿æäœ
proxy.testã¯targetããã®å€ãè¿ããŸãã proxyã®ã€ãã¬ãŒãã¯ãtargetããã®å€ãè¿ããŸãã
ã芧ã®éãããã©ããããªãå Žå㯠proxy 㯠target ã«å¯Ÿããééçãªã©ãããŒã§ãã
Proxy ã¯ç¹å¥ãª âãšããŸããã¯ãªããžã§ã¯ã(exotic object)â ã§ããProxy ã¯ç¬èªã®ããããã£ã¯æã£ãŠããŸããã空㮠handler ã®å Žåã¯ãééçã« target ãžæäœã転éããŸãã
ããã«æ©èœãæå¹ã«ããããã«ããã©ããã远å ããŸãããã
ããã«ãã£ãŠãäœãã€ã³ã¿ãŒã»ããã§ããã§ãããïŒ
ãªããžã§ã¯ãã«å¯Ÿããã»ãšãã©ã®æäœã«å¯ŸããŠã¯ãJavaScript ã®ä»æ§ã§ ãããã âå
éšã¡ãœããâ ãšåŒã°ãããã®ãããã仿§ã§ã¯ããããã©ã®ããã«åäœããããæãäœã¬ãã«ã§èª¬æããŠããŸããäŸãã°ã [[Get]] ã¯ãããããã£ãèªã¿åãããã®å
éšã¡ãœããã§ã[[Set]] ã¯ããããã£ãæžã蟌ãããã®å
éšã¡ãœããããªã©ã§ãããããã®ã¡ãœããã¯ä»æ§ã§ã®ã¿äœ¿çšãããŠãããååã䜿ã£ãŠããããçŽæ¥äœ¿çšããããšã¯ã§ããŸããã
ãããã·ã®ãã©ããã¯ãããã®ã¡ãœããã®åŒã³åºããã€ã³ã¿ãŒã»ããããŸãããããã®ã¡ãœããã¯Proxy specification åã³ä»¥äžã®è¡šã«ãªã¹ããããŠããŸãã
ãã®ããŒãã«ã«ããã¹ãŠã®å
éšãœããã«å¯Ÿãããã©ããããããŸã: æäœãã€ã³ã¿ãŒã»ããããããã« new Proxy ã® handler ãã©ã¡ãŒã¿ã«è¿œå ã§ããã¡ãœããåã§ã:
| å éšã¡ãœãã | ãã³ãã©ã¡ãœãã | ãã€çºçããã |
|---|---|---|
[[Get]] |
get |
ããããã£èªã¿åãæ |
[[Set]] |
set |
ããããã£æžãèŸŒã¿æ |
[[HasProperty]] |
has |
in æŒç®å |
[[Delete]] |
deleteProperty |
delete æŒç®å |
[[Call]] |
apply |
颿°åŒã³åºã |
[[Construct]] |
construct |
new æŒç®å |
[[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 |
JavaScript ã«ã¯ããã€ãã®äžå€æ¡ä»¶(å éšã¡ãœãããš ãã©ããã«ãã£ãŠæºããããã¹ãæ¡ä»¶)ããããŸãã
ãã®ã»ãšãã©ã¯æ»ãå€ã«é¢ããŠã§ã:
[[Set]]ã¯å€ãæ£åžžã«æžã蟌ãŸããå Žåã«ã¯trueããããã§ãªããã°falseãè¿ãå¿ èŠããããŸãã[[Delete]]ã¯å€ãæ£åžžã«åé€ãããå Žåã«ã¯trueããããã§ãªããã°falseãè¿ãå¿ èŠããããŸãã- âŠãªã©ã§ãã以äžã®äŸã§è©³ããèŠãŠãããŸãã
ä»ã«ã以äžã®ãããªããã€ãã®äžå€æ¡ä»¶ããããŸã:
- proxy ãªããžã§ã¯ãã«é©çšããã
[[GetPrototypeOf]]㯠proxy ãªããžã§ã¯ãã®ã¿ãŒã²ãããªããžã§ã¯ãã«é©çšããã[[GetPrototypeOf]]ãšåãå€ãè¿ããªããã°ãªããŸãããã€ãŸããproxy ã®ãããã¿ã€ããåç §ãããšãåžžã«ã¿ãŒã²ãããªããžã§ã¯ãã®ãããã¿ã€ããè¿åŽãããå¿ èŠããããŸãã
traps ã¯ãããã®æäœãã€ã³ã¿ãŒã»ããã§ããŸããããããã®ã«ãŒã«ã«ã¯åŸãå¿ èŠããããŸãã
äžå€æ¡ä»¶ã¯ãèšèªæ©èœã®æ£ãããšäžè²«ããåäœãä¿èšŒãããã®ã§ããå®å šãªäžå€æ¡ä»¶ã®ãªã¹ãã¯ ä»æ§ã«ãããŸãããå€ãªããšãããªãéãã¯éåããããšã¯ãªãã§ãããã
å®éã®äŸã§ãããã©ã®ããã«åäœããã®ããèŠãŠã¿ãŸãããã
âgetâ ãã©ããã§ã®ããã©ã«ãå€
æãäžè¬çãªãã©ãã(traps)ã¯ããããã£ã®èªã¿æžãã§ãã
èªã¿åããã€ã³ã¿ãŒã»ããããã«ã¯ãhandler ã« get(target, property, receiver) ãå¿
èŠã§ãã
ããã¯ããããã£ãèªã¿åããããšãã以äžã®åŒæ°ã§å®è¡ãããŸãã:
target:new Proxyã®æåã®åŒæ°ãšããŠæž¡ãããã¿ãŒã²ãããªããžã§ã¯ãã§ããpropertyâ ããããã£å,receiver--ã¿ãŒã²ããããããã£ã getter ã®å Žåãreceiverã¯ãã®åŒã³åºãã®äžã§thisãšããŠäœ¿ããããªããžã§ã¯ãã§ããéåžžãããã¯proxyãªããžã§ã¯ãèªèº«(ãããã¯ãproxy ããç¶æ¿ããŠããå Žåã¯ãç¶æ¿ãããªããžã§ã¯ã)ã§ããçŸæç¹ã§ã¯ãã®åŒæ°ã¯äžèŠã§ãã詳现ã«ã€ããŠã¯åŸã»ã©èª¬æããŸãã
ãªããžã§ã¯ãã®ããã©ã«ãå€ãå®è£
ããã®ã« get ã䜿ã£ãŠã¿ãŸãããã
ååšããªãå€ã®å Žå 0 ãè¿ãæ°å€é
åãäœããŸãã
éåžžãååšããªãå€ãååŸããããšãããš undefined ã«ãªããŸãããããã§ã¯éåžžã®é
åã«å¯ŸããŠãããããã£ãååšããªãå Žåã« 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 (ãã®ãããªé
ç®ã¯ãªã)
ã芧ã®éããget ãã©ããã䜿çšããã®ã¯éåžžã«ç°¡åã§ãã
Proxy ãå©çšãããšãä»»æã® âããã©ã«ãå€â çšã®ããžãã¯ãçµãããšãã§ããŸãã
æ³åããŠãã ããããã¬ãŒãºãšäžç·ã«ç¿»èš³ãæã€èŸæžããããšããŸã:
let dictionary = {
'Hello': 'Hola',
'Bye': 'Adiós'
};
alert( dictionary['Hello'] ); // Hola
alert( dictionary['Welcome'] ); // undefined
çŸåšããã¬ãŒãºããªãå Žåãdictionary ã®èªã¿åã㯠undefined ãè¿ããŸããããããå®éã«ã¯ undefined ãããæªç¿»èš³ã®ãŸãŸã®ãã¬ãŒãºãæ®ãã»ããããã§ãããªã®ã§ããã®ãããªå Žåã« undefined ã§ã¯ãªããæªç¿»èš³ã®ãã¬ãŒãºãè¿ãããã«ããŸãããã
ãã®ããã«ã¯ãdirectory ãèªã¿åãæäœãã€ã³ã¿ãŒã»ãããããããã·ã§ã©ããããŸãã:
let dictionary = {
'Hello': 'Hola',
'Bye': 'Adiós'
};
dictionary = new Proxy(dictionary, {
get(target, phrase) { // èŸæž(dictionary)ããã®ããããã£èªã¿åããã€ã³ã¿ãŒã»ãã
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, ...);
ãããã·ã¯ã©ãã§ãã¿ãŒã²ãããªããžã§ã¯ããå®å šã«çœ®ãæããå¿ èŠããããŸãããããã·ãããåŸã¯ã¿ãŒã²ãããªããžã§ã¯ããåç §ããªãã§ãã ãããåç §ãããšãç°¡åã«å°ç¡ãã«ãªããŸãã
âsetâ ãã©ããã§ã®ããªããŒã·ã§ã³
æ°å€å°çšã®é åãã»ãããšããŸããããå¥ã®åã®å€ã远å ãããå Žåããšã©ãŒã«ããå¿ èŠããããŸãã
set ãã©ããã¯ããããã£ãæžã蟌ãŸãããšãã«çºçããŸãã
set(target, property, value, receiver):
target:new Proxyã®æåã®åŒæ°ãšããŠæž¡ãããã¿ãŒã²ãããªããžã§ã¯ãã§ããproperty: ããããã£åvalue: ããããã£å€,receiver:getãšåæ§ã§ãsetter ããããã£ã«é¢ä¿ããŸãã
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' ã false ãè¿åŽ)
alert("This line is never reached (error in the line above)");
泚ç®ããŠãã ãã: é
åã®çµã¿èŸŒã¿ã®æ©èœã¯äŸç¶ãšããŠåäœããŸã! å€ã¯ push ã«ãã远å ãããŸãããlength ããããã£ã¯å€ã远å ããããšãã«ãªãŒãã€ã³ã¯ãªã¡ã³ããããŸãããããã·ã¯äœãç Žå£ããŠããŸããã
æã
ã¯ãã§ãã¯åŠçã远å ããã®ã« push ã unshift ã®ãããªãå€ã远å ããé
åã¡ãœãããäžæžãããå¿
èŠã¯ãããŸããããªããªãããããã¯å
éšçã«ã¯ [[Set]] æäœã䜿çšããŠããããããã·ã«ããã€ã³ã¿ãŒã»ãããããããã§ãã
ãããã£ãŠãã³ãŒãã¯ã¯ãªãŒã³ã§ããç°¡æœã§ãã
true ãè¿ãã®ãå¿ããªãã§ãã ããäžèšã®ããã«ãç¶æãã¹ãæ¡ä»¶ããããŸãã
set ã®å Žåãæžã蟌ã¿ã®æåã«å¯ŸããŠã¯ true ãè¿ããªããã°ãªããŸããã
ãããå¿ããã false ãè¿ããšãæäœã¯ TypeError ãããªã¬ãŒããŸãã
âownKeysâ ãš âgetOwnPropertyDescriptorâ ã«ããã€ãã¬ãŒã·ã§ã³
Object.keys, for..in ã«ãŒãåã³ãªããžã§ã¯ãããããã£ãã€ãã¬ãŒãããä»ã®ã»ãšãã©ã®ã¡ãœãã㯠[[OwnPropertyKeys]] å
éšã¡ãœãã(ownKeys ãã©ããã«ããã€ã³ã¿ãŒã»ããããã)ã䜿çšããŠããããã£ã®ãªã¹ããååŸããŠããŸãã
ãã®ãããªã¡ãœããã®è©³çްã¯ç°ãªããŸã:
Object.getOwnPropertyNames(obj)㯠âéâ ã·ã³ãã«ããŒãè¿ããŸããObject.getOwnPropertySymbols(obj)ã¯ã·ã³ãã«ããŒãè¿ããŸããObject.keys/values()ã¯enumerableãã©ã°(ããããã£ãã©ã°ã«ã€ããŠã¯ããã£ãã¿ãŒ ããããã£ãã©ã°ãšãã£ã¹ã¯ãªãã¿ ã«èª¬æããããŸã)ãæã€éã·ã³ãã«ã®ããŒ/ããªã¥ãŒå€ãè¿ããŸããfor..inã¯enumerableãã©ã°ãæã€éã·ã³ãã«ããŒãšãããã¿ã€ãããŒãã«ãŒãããŸãã
âŠãããããããã¯ãã¹ãŠãã®å éšã¡ãœããã§åŸããããªã¹ãããå§ãŸããŸãã
以äžã®äŸã§ã¯ãownKeys ãã©ããã䜿çšã㊠user ã«å¯Ÿãã for..in ã«ãŒããè¡ãããŸã 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" 㯠_password ãé€å€ããŸã
for(let key in user) alert(key); // name, then: age
// ãããã®ã¡ãœãããžãåã圱é¿ããããŸã:
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) ); // <empty>
ãªãã§ãããïŒçç±ã¯ç°¡åã§ãã: Object.keys 㯠enumerable ãã©ã°ãæã€ããããã£ã ããè¿ãããã§ããããã確ãããããããã¹ãŠã®ã¡ãœããã«å¯Ÿãå
éšã¡ãœãã [[GetOwnProperty]] ãåŒã³åºã,ãã£ã¹ã¯ãªãã¿ ãååŸããŸãããããšãããã§ã¯ããããã£ããªãã®ã§ããã®ãã£ã¹ã¯ãªãã¿ã¯ç©ºã§ãããenumerable ãã©ã°ããããŸããããã®ãããã¹ããããããŸãã
Object.keys ãããããã£ãè¿ãã«ã¯ãenumerable ä»ãã§ãªããžã§ã¯ãã«ååšãããã[[GetOwnProperty]](ãã©ãã㯠getOwnPropertyDescriptor)ã®åŒã³åºããã€ã³ã¿ãŒã»ãããã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â åã³ä»ã®ãã©ããã§ä¿è·ãããããããã£
ã¢ã³ããŒã¹ã³ã¢ _ ã§å§ãŸãããããã£ãã¡ãœããã¯å
éšçãªãã®ã§ãããšããããšã¯ãåºãç¥ãããæ
£ç¿ã§ãããããã¯ãªããžã§ã¯ãã®å€ããã¢ã¯ã»ã¹ãããã¹ãã§ã¯ãããŸããã
ã§ãããæè¡çã«ã¯å¯èœã§ã:
let user = {
name: "John",
_password: "secret"
};
alert(user._password); // secret
ãããã·ã䜿çšããŠã_ ã§å§ãŸãããããã£ãžã®ã¢ã¯ã»ã¹ãé²ããŸãããã
次ã®ãã©ãããå¿ èŠã§ã:
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) { // ããããã£ã®åé€ãã€ã³ã¿ãŒã»ãã
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
(*) è¡ã® 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 ãžã®ã¢ã¯ã»ã¹ã詊ã¿ããš get ãã©ãããæ©èœ(ããã¯ããããããããã£èªã¿åãã§ããªã¬ãŒãããŸã)ãããšã©ãŒãã¹ããŒããŸãã
ãã®ããã(*) ã®éããªããžã§ã¯ãã¡ãœããã®ã³ã³ããã¹ããå
ã®ãªããžã§ã¯ãã§ãã target ã§ãã€ã³ãããŸãã以éããã®åŒã³åºãã§ã¯ this ãšããŠãã©ããã®ãªã target ã䜿çšããŸãã
ãã®è§£æ±ºçã¯ãããŠãåäœããŸãããã¡ãœããããããã·ãããŠããªããªããžã§ã¯ããå¥ã®å Žæã«æž¡ãå¯èœæ§ãããããçæ³çã§ã¯ãããŸãããããã¯æ··ä¹±ã®ããšã«ãªããŸã: ã©ãã«ãªãªãžãã«ã®ãªããžã§ã¯ãããããã©ãããããã·ããããã®ãªã®ãã
ããã«ããªããžã§ã¯ããäœåºŠããããã·ãããå¯èœæ§ããããŸã(è€æ°ã®ãããã·ãããããç°ãªã â埮調æŽâ ããªããžã§ã¯ãã«ããå ŽåããããŸã)ããŸããã¡ãœããã«ã©ãããããŠããªããªããžã§ã¯ããæž¡ããå Žåãäºæããªãçµæã«ãªãå¯èœæ§ããããŸãã
ãããã£ãŠããã®ãããªãããã·ã¯äœ¿çšããªãããšãæšå¥šããŸãã
ã¢ãã³ãª JavaScript ãšã³ãžã³ã¯ã¯ã©ã¹ã® private ããããã£ããã€ãã£ãã«ãµããŒãããŸã(# ããå§ãŸããŸã)ãããã«ã€ããŠã¯ãã£ãã¿ãŒ Private / protected ããããã£ãšã¡ãœãã ã§èšèŒããŠããŸãããããã·ã¯å¿
èŠãããŸããã
ãã ãããã®ãããªããããã£ã«ãåé¡ã¯ãããŸããç¹ã«ãããã¯ç¶æ¿ãããŸããã
âhasâ ãã©ããã䜿çšãã âç¯å²å â
ä»ã®äŸãèŠãŠã¿ãŸãããã
ç¯å²ãæã€ãªããžã§ã¯ãããããŸã:
let range = {
start: 1,
end: 10
};
in æŒç®åã䜿ã£ãŠã æ°å€ã range ã®ç¯å²å
ã«ãããã確èªããŸãã
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
è¯ãç³è¡£æ§æã§ãããããã«å®è£ ããšãŠãç°¡åã§ãã
Wrapping functions: âapplyâ
颿°ã®åšãã«å¯ŸããŠãåæ§ã« proxy ãã©ããããããšãã§ããŸãã
apply(target, thisArg, args) ãã©ããã¯ãããã·ã颿°ãšããŠåŒã³åºãããåŠçãããŸã:
targetã¯ã¿ãŒã²ãããªããžã§ã¯ãã§ã(JavaScript ã§ã¯é¢æ°ã¯ãªããžã§ã¯ãã§ã),thisArgã¯thisã®å€ã§ãargsã¯åŒæ°ã®ãªã¹ãã§ã
äŸãã°ããã£ãã¿ãŒ ãã³ã¬ãŒã¿ãšè»¢é, call/apply ã§è¡ã£ã delay(f, ms) ãã³ã¬ãŒã¿ãæãåºããŠãã ããã
ãã®ãã£ãã¿ãŒã§ã¯ãproxy ã䜿ããã«å®çŸããŸãããdelay(f, ms) ã®åŒã³åºãã¯ãms ããªç§åŸã« f ã®åŒã³åºããè¡ã颿°ãè¿ããŸããã
ããã¯ä»¥åã®é¢æ°ããŒã¹ã®å®è£ ã§ã:
function delay(f, ms) {
// ã¿ã€ã ã¢ãŠãåŸã« f ãžã®åŒã³åºããæž¡ãã©ãããŒé¢æ°ãè¿ããŸã
return function() { // (*)
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(user) {
alert(`Hello, ${user}!`);
}
// ãã®ã©ããããããšãsahHi åŒã³åºã㯠3ç§éé
å»¶ããŸã
sayHi = delay(sayHi, 3000);
sayHi("John"); // Hello, John! (3ç§åŸ)
ãã§ã«ã芧ã«ãªã£ãããã«ãããã¯ã»ãŒã»ãŒæ©èœããŸããã©ãããŒé¢æ° (*) ã¯ã¿ã€ã ã¢ãŠãåŸã«åŒã³åºããå®è¡ããŸãã
ããããã©ãããŒé¢æ°ã¯ããããã£ã®èªã¿æžãæäœãªã©ã¯è»¢éããŸãããã©ããããåŸã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 ã¯å®£èšããã颿°ã®åŒæ°ã®æ°ãè¿ããŸã)
sayHi = delay(sayHi, 3000);
alert(sayHi.length); // 0 (ã©ãããŒåŸã¯åŒæ°ã¯ 0 ã§ã)
Proxy ã¯ãã¹ãŠãã¿ãŒã²ãããªããžã§ã¯ãã«è»¢éããã®ã§ãã¯ããã«åŒ·åã§ãã
颿°ã©ããã³ã°ã®ä»£ããã« 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 (*) ãããã·ã¯ length æäœãã¿ãŒã²ããã«è»¢éããŸã
sayHi("John"); // Hello, John! (3ç§åŸ)
çµæã¯åãã§ãããåŒã³åºãã ãã§ãªãããããã·äžã®ãã¹ãŠã®æäœã¯å
ã®é¢æ°ã«è»¢éãããŸãããã®ãããè¡ (*) ã§ sayHi.length ã¯ã©ããã³ã°åŸãæ£ããå€ãè¿ããŸãã
ããã§ âãããªãããªâ ã©ãããŒãæã«å ¥ããŸããã
ä»ã«ããã©ããã¯ãããŸã: å®å šãªãªã¹ãã¯ãã®ãã£ãã¿ãŒã®æåã«ã®ããŠããŸãããããã®äœ¿çšãã¿ãŒã³ã¯äžèšãšåãã§ãã
Reflect
Reflect 㯠Proxy ã®äœæãç°¡åã«ããçµã¿èŸŒã¿ã®ãªããžã§ã¯ãã§ãã
以å説æãããšããã[[Get]], [[Set]] ããã®ä»ã®å
éšã¡ãœããã¯ä»æ§äžã®ãã®ã§ãããçŽæ¥åŒã³åºãããšã¯ã§ããŸããã
Reflect ãªããžã§ã¯ãã¯ãããããããå¯èœã«ããŸããããã®ãã€ã¡ãœããã¯å
éšã¡ãœããã®æå°éã®ã©ãããŒã§ãã
ããã§ã¯ãæäœãšããããšåãããšããã Reflect åŒã³åºãã®äŸã瀺ããŸã:
| æäœ | Reflect åŒã³åºã |
å éšã¡ãœãã |
|---|---|---|
obj[prop] |
Reflect.get(obj, prop) |
[[Get]] |
obj[prop] = value |
Reflect.set(obj, prop, value) |
[[Set]] |
delete obj[prop] |
Reflect.deleteProperty(obj, prop) |
[[HasProperty]] |
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, âŠ)ãšããŠåŒã³åºãããšãã§ããŸããããã¯è峿·±ãæ©èœã§ãããããã§ã¯å¥ã«éèŠãªéšåããããŸãã
Proxy ã§ãã©ããå¯èœãªãã¹ãŠã®å
éšã¡ãœããã«å¯ŸããReflect ã«ã¯ Proxy ãã©ãããšåãååãåŒæ°ãæã€å¯Ÿå¿ããã¡ãœããããããŸãã
ãããã£ãŠã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; // "GET name" ã衚瀺
user.name = "Pete"; // "SET name=Pete" ã衚瀺
Here:
Reflect.getã¯ãªããžã§ã¯ãããããã£ãèªã¿åããŸããReflect.setã¯ãªããžã§ã¯ãããããã£ã®æžã蟌ã¿ãè¡ããæåããã°trueãè¿ããŸãããã以å€ã®å Žåã¯falseãè¿ããŸãã
ã€ãŸãããã¹ãŠã¯åçŽã§ã: ãã©ãããåŒã³åºãããªããžã§ã¯ãã«è»¢éãããå ŽåãåãåŒæ°ã§ Reflect.<method> ãåŒã¹ã°ããã§ãã
ã»ãšãã©ã®å Žåã§ãReflect ã䜿ãããšãªãåãããšãã§ããŸããäŸãã°ãããããã£ã®èªã¿åã Reflect.get(target, prop, receiver) 㯠target[prop] ã«çœ®ãæããããšãã§ããŸããã§ãããéèŠãªæå³åãããããŸãã
ã²ãã¿ãŒ(getter)ã®ãããã·
ãªã Reflect.get ãåªããŠããçç±ã瀺ããã¢ãèŠãŠã¿ãŸããããåãããŠããªã get/set ãïŒçªç®ã®åŒæ° receiver ãæã£ãŠããã®ã(ããã¯ä»¥åã¯äœ¿çšããŠããŸããã§ãã)ãèŠãŠãããŸãããã
_name ããããã£ãã〠user ãªããžã§ã¯ããããããã®ã²ãã¿ãŒãããŸã:
ããã¯ãã®ãããã·ã§ã:
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
ããã§ã¯ãget ãã©ããã¯æçœã§ããå
ã®ããããã£ãè¿ããä»ã«ã¯äœãããŠããŸãããä»åã®äŸã§ã¯ããã§ååã§ãã
ä»ã®ãšãããã¹ãŠåé¡ãããŸãããã§ã¯äŸãããå°ãè€éã«ããŠã¿ãŸãããã
user ããå¥ã®ãªããžã§ã¯ã admin ãç¶æ¿ãããšãæ£ãããªãæ¯ãèããèµ·ããŸã:
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"
};
// æåŸ
å€: Admin
alert(admin.name); // åºå: Guest (?!?)
admin.name ã®èªã¿åã㯠"Guest" ã§ã¯ãªã "Admin" ãè¿ãã¹ãã§ã!
äœãèµ·ããã®ã§ããããïŒç¶æ¿ã«ãªã«ãåé¡ããã£ãã®ã§ããããïŒ
ã§ããããããã·ãåé€ãããšãã¹ãŠæåŸ éãã«åäœããŸãã
åé¡ã¯è¡ (*) ã®ãããã·ã®äžã«ãããŸãã
-
admin.nameãèªã¿åããšããadminãªããžã§ã¯ãã«ã¯ãã®ãããªããããã£ã¯ãªããããæ€çŽ¢ã¯ãã®ãããã¿ã€ãã«é²ã¿ãŸãã -
ãããã¿ã€ãã¯
userProxyã§ãã -
ãããã·ãã
nameããããã£ãèªã¿åããšãgetãã©ãããçºçããè¡(*)ã§target[prop]ã«ããå ã®ãªããžã§ã¯ãããè¿åŽãããŸããpropãã²ãã¿ãŒã§ããå Žåãtarget[prop]ã®åŒã³åºãã¯ã³ã³ããã¹ãthis=targetã§ã³ãŒããå®è¡ãããŸãããã®ãããçµæã¯å ã®ãªããžã§ã¯ãtarget, ã€ãŸãuserããã®this._nameã«ãªããŸãã
ãããä¿®æ£ããã«ã¯ãget ãã©ããã®3çªç®ã®åŒæ°ã§ãã receiver ãå¿
èŠã§ããããã«ããã²ãã¿ãŒã«æ£ãã 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
äžã®ã³ãŒãã§ã¯ãæ£ãã this (ã€ãŸã admin) ãžã®åç
§ãç¶æãã receiver ã¯ãè¡ (*) ã§ Reflect.get ã䜿çšããã²ãã¿ãŒã«æž¡ãããŸãã
ãã©ãããããã«çãæžãããšãã§ããŸã:
get(target, prop, receiver) {
return Reflect.get(...arguments);
}
Reflect åŒã³åºãã¯ãã©ãããšãŸã£ããåãååãä»ããããŠãããåãåŒæ°ãåãä»ããŸããç¹å¥ã«ãã®ããã«èšèšãããŸããã
ãããã£ãŠãreturn Reflect... ã¯å®å
šãã€èãããŸã§ããªãåãããããææ®µã§æäœã転éããããšãã§ããŸãã
ãããã·ã®å¶é
ãããã·ã¯æ¢åã®ãªããžã§ã¯ãã®åäœãæãäœãã¬ãã«ã§å€æŽããã埮調æŽããç¬èªã®æ¹æ³ãæäŸããŸããããã§ãå®ç§ã§ã¯ãããŸãããããã€ãå¶éããããŸãã
çµã¿èŸŒã¿ãªããžã§ã¯ã: å éšã¹ããã(Internal slots)
Map, Set, Date, Promise ãªã©ã®å€ãã®çµã¿èŸŒã¿ãªããžã§ã¯ãã¯ããããã âå
éšã¹ãããâ ã䜿çšããŸãã
ãããã¯ããããã£ã«äŒŒãŠããŸãããå
éšã§ä»æ§å°çšã®ç®çã§äºçŽãããŠããŸããäŸãã°ãMap ã¯å
éšã¹ããã [[MapData]] ã«ã¢ã€ãã ãä¿åããŸããçµã¿èŸŒã¿ã®ã¡ãœããã¯ã[[Get]]/[[Set]] å
éšã¡ãœããçµç±ã§ã¯ãªããçŽæ¥ã¢ã¯ã»ã¹ããŸãããã®ãããProxy ã¯ã€ã³ã¿ãŒã»ããããããšãã§ããŸããã
å éšã®è©±ãªã®ã«æ°ã«ããå¿ èŠã¯ããã®ã§ããããïŒ
ããã«åé¡ããããŸãããã®ãããªçµã¿èŸŒã¿ã®ãªããžã§ã¯ãããããã·ããããšããããã·ã¯ãããã®å éšã¹ããããæããªããããçµã¿èŸŒã¿ã®ã¡ãœããã¯å€±æããŸãã
äŸ:
let map = new Map();
let proxy = new Proxy(map, {});
proxy.set('test', 1); // Error
å
éšçã«ãMap ã¯ãã¹ãŠã®ããŒã¿ã [[MapData]] å
éšã¹ãããã«ä¿åããŸãããããã·ã¯ãã®ãããªã¹ãããã¯ãããŸãããçµã¿èŸŒã¿ã®ã¡ãœãã Map.prototype.set ã¡ãœããã¯å
éšãããã㣠this.[[MapData]] ã«ã¢ã¯ã»ã¹ããããšããŸãããthis=proxy ãªã®ã§ 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!)
äžã®äŸã§ã¯ãget ãã©ãã㯠map.set ãªã©ã®é¢æ°ããããã£ãã¿ãŒã²ãããªããžã§ã¯ã(map)èªèº«ã«ãã€ã³ãããã®ã§ãåé¡ãªãåäœããŸãã
ãããŸã§ã®äŸãšã¯éããproxy.set(...) å
ã§ã® this ã®å€ã¯ proxy ã§ã¯ãªãå
ã® map ã«ãªããŸãããã®ãããset ã®å
éšå®è£
ã this.[[MapData]] å
éšã¹ãããã«ã¢ã¯ã»ã¹ããã®ã¯æåããŸãã
Array ã«ã¯å
éšã¹ãããããããŸããæ³šç®ãã¹ãäŸå€ã§ã: çµã¿èŸŒã¿ã® Array ã¯å
éšã¹ãããã䜿çšããŠããŸãããArray ã¯ãã£ãšä»¥åããååšããŠããããšããããæŽå²çãªçç±ã«ãããã®ã§ãã
ãããã£ãŠé åããããã·ããéã«ã¯ãã®ãããªåé¡ã¯èµ·ãããŸããã
ãã©ã€ããŒããã£ãŒã«ã
䌌ããããªããšããã©ã€ããŒãã¯ã©ã¹ãã£ãŒã«ãã§ãèµ·ãããŸãã
äŸãã°ãgetName() ã¡ãœããã¯ãããã·åŸã«ãã©ã€ããŒã #name ããããã£ãžã¢ã¯ã»ã¹ãããšå£ããŸãã:
class User {
#name = "Guest";
getName() {
return this.#name;
}
}
let user = new User();
user = new Proxy(user, {});
alert(user.getName()); // Error
ããã¯ããã©ã€ããŒããã£ãŒã«ããå
éšã¹ãããã䜿çšããŠå®è£
ãããŠããããã§ããJavaScript ã¯ãããã«ã¢ã¯ã»ã¹ããéã[[Get]]/[[Set]] ã¯äœ¿çšããŸããã
getName() ã®åŒã³åºãã§ã¯ãthis ã®å€ã¯ãããã·ããã user ã§ããããã©ã€ããŒããã£ãŒã«ãã®ã¹ããããæã£ãŠããŸããã
ãã®å Žåããã¡ãœããããã€ã³ãããæ¹æ³ã§æ©èœãããããšãã§ããŸã:
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
ãã ãããã®è§£æ±ºçã«ãæ¬ ç¹ããããŸãã以å説æãããšããããã®æ¹æ³ã¯å ã®ãªããžã§ã¯ããã¡ãœããã«å ¬éããã®ã§ãã¡ãœããã®åŠçã«ãã£ãŠã¯ããã«ãªããžã§ã¯ããæž¡ãããå¯èœæ§ããããä»ã®ãããã·ãããæ©èœãç Žå£ããå¯èœæ§ããããŸãã
Proxy != target
Proxy ãšå ã®ãªããžã§ã¯ãã¯ç°ãªããªããžã§ã¯ãã§ããããã¯åœç¶ã§ããã
ãªã®ã§ãå ã®ãªããžã§ã¯ããããŒãšããŠäœ¿çšãããã®åŸãããã·ãããšããããã·ã¯èŠã€ãããŸããã:
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
ã芧ã®éãããããã·åŸã¯ã»ãã allUsers ã§ user ãèŠã€ããããšãã§ããŸããããããã·ã¯ç°ãªããªããžã§ã¯ãã ããã§ãã
=== ãã€ã³ã¿ãŒã»ããããããšã¯ã§ããŸãããããã·ã¯ new(construct), in(has), delete(deleteProperty)ãªã©ã®å€ãã®æŒç®åãã€ã³ã¿ãŒã»ããããããšãã§ããŸãã
ãããããªããžã§ã¯ããžã®å³å¯ç䟡ãã¹ããã€ã³ã¿ãŒã»ããããæ¹æ³ã¯ãããŸããããªããžã§ã¯ãã¯èªèº«ã«ã®ã¿å³å¯ã«çãããä»ã®å€ãšã¯çãããããŸããã
ãããã£ãŠããªããžã§ã¯ãã®çäŸ¡ãæ¯èŒãããã¹ãŠã®æŒç®åãšçµã¿èŸŒã¿ã®ã¯ã©ã¹ã¯ãªããžã§ã¯ããšãããã·ãåºå¥ããŸããããã«ã¯ééçãªæ¿ããã¯ãããŸããã
åãæ¶ãå¯èœ(revocable)ãªãããã·
åãæ¶ãå¯èœ(revocable) ãªãããã·ã¯ãç¡å¹ã«ããããšã®ã§ãããããã·ã§ãã
ãªãœãŒã¹ã«å¯ŸããŠããã€ã§ãã¢ã¯ã»ã¹ãéããããããã«ããããšããŸãããã
ãã®æ¹æ³ãšããŠã¯ããªãœãŒã¹ããã©ãããããªãåãæ¶ãå¯èœãªãããã·ã§ã©ããããããšã§ãããã®ãããªãããã·ã¯ãªããžã§ã¯ããžæäœã転éãã€ã€ããã€ã§ããããç¡å¹ã«ããããšãã§ããŸãã
æ§æã¯æ¬¡ã®éãã§ã:
let {proxy, revoke} = Proxy.revocable(target, handler)
ãã®åŒã³åºã㯠proxy ãšç¡å¹ã«ããããã« revoke 颿°ãæã€ãªããžã§ã¯ããè¿ããŸãã
äŸ:
let object = {
data: "Valuable data"
};
let {proxy, revoke} = Proxy.revocable(object, {});
// ãªããžã§ã¯ãã®ä»£ããã«ãããã·ãã©ããã«æž¡ããŸã
alert(proxy.data); // Valuable data
// åŸã§æ¬¡ã®ããã«ããŸã
revoke();
// ãããšããããã·ã¯æ©èœããªããªããŸã(ç¡å¹åãããŸãã)
alert(proxy.data); // Error
revoke() åŒã³åºãã¯ããããã·ããã¿ãŒã²ãããªããžã§ã¯ããžã®ãã¹ãŠã®å
éšåç
§ãåé€ããŸããããã«ããç¹ããããªããªããŸãã
åæç¶æ
ã§ãrevoke 㯠proxy ãšã¯å¥ãªã®ã§ãçŸåšã®ã¹ã³ãŒãã« revoke ãæ®ãããŸãŸãproxy ãæž¡ãããšãå¯èœã§ãã
proxy.revoke = revoke ãšèšå®ããããšã§ãproxy ã« revoke ã¡ãœããããã€ã³ãããããšãã§ããŸãã
å¥ã®éžæè¢ã¯ãWeakMap ãäœæããããŒãšã㊠proxy ããå€ãšããŠå¯Ÿå¿ãã revoke ãããããããšã§ããããã§ãç°¡åã« proxy ã«å¯Ÿãã revoke ãèŠã€ããããšãã§ããŸãã
let revokes = new WeakMap();
let object = {
data: "Valuable data"
};
let {proxy, revoke} = Proxy.revocable(object, {});
revokes.set(proxy, revoke);
// ..later in our code..
revoke = revokes.get(proxy);
revoke();
alert(proxy.data); // Error (revoked)
ããã§ Map ã®ä»£ããã« WeakMap ã䜿çšããŠããã®ã¯ãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ããããã¯ããªãããã«ããããã§ããproxy ãªããžã§ã¯ãã âå°éäžå¯èœâ ã«ãªã£ã(e.g ãããåç
§ãã倿°ããªããªã£ã)å ŽåãWeakMap ãå©çšãããšãäžèŠã«ãªã£ã revoke ãäžç·ã«ã¡ã¢ãªäžããåé€ããããšãã§ããŸãã
ãªãã¡ã¬ã³ã¹
ãµããª
Proxy ã¯ãªããžã§ã¯ãã®ã©ãããŒã§ãããæäœããªããžã§ã¯ããžè»¢éããå¿
èŠã«å¿ããŠãã®äžéšããã©ããããŸãã
ã¯ã©ã¹ã颿°ãå«ããããããçš®é¡ã®ãªããžã§ã¯ããã©ããããããšãã§ããŸãã
æ§æ:
let proxy = new Proxy(target, {
/* traps */
});
âŠãã以éã¯ã©ãã§ã target ã®ä»£ããã« proxy ã䜿ãå¿
èŠããããŸãããããã·ã¯ç¬èªã®ããããã£ãã¡ãœããã¯æã£ãŠããŸããããã©ãããæå®ãããŠããã°æäœããã©ããããããã§ãªããã° target ãªããžã§ã¯ãã«è»¢éããŸãã
以äžããã©ããããããšãã§ããŸã:
- ããããã£(ååšããªããã®ãå«ã)ã®èªã¿åã(
get)ãæžã蟌ã¿(set)ãåé€(deleteProperty) - 颿°åŒã³åºã(
applyãã©ãã) newæŒç®å(constructãã©ãã)- ãã®ä»å€ãã®ãã©ãã(å®å šãªãªã¹ãã¯ãã®èšäºã®åé ãš docsã«ãããŸãã)
ããã«ãããâä»®æ³ã®â ããããã£ãã¡ãœãããäœæããããããã©ã«ãå€ããªãã¶ãŒããã«ãªããžã§ã¯ãã颿°ãã³ã¬ãŒã¿ãªã©æ§ã ãªãã®ãå®è£ ããããšãã§ããŸãã
ãŸããç°ãªããããã·ã§è€æ°åãªããžã§ã¯ããã©ããããæ©èœã®æ§ã ãªåŽé¢ã§ãªããžã§ã¯ããã³ã¬ãŒãããããšãå¯èœã§ãã
Reflect API 㯠Proxy ãè£å®ããããã®ãã®ãšããŠèšèšãããŠããŸãããã¹ãŠã® Proxy ãã©ããã«å¯ŸããŠãåãåŒæ°ãæã€ Reflect åŒã³åºãããããŸãããããã䜿çšããŠã¿ãŒã²ãããªããžã§ã¯ãã«è»¢éããå¿
èŠããããŸãã
ãããã·ã«ã¯ããã€ãå¶éããããŸã:
- çµã¿èŸŒã¿ã®ãªããžã§ã¯ãã«ã¯ âå éšã¹ãããâ ããããããããžã®ã¢ã¯ã»ã¹ã¯ãããã·ããããšã¯ã§ããŸãããäžèšã®åé¿çãåç §ããŠãã ããã
- ãã©ã€ããŒãã¯ã©ã¹ãã£ãŒã«ãã«ãåãããšãåœãŠã¯ãŸããŸãããããã¯å
éšçã«ã¯ã¹ãããã䜿çšããŠå®è£
ãããŠããããããããã·ãããã¡ãœããåŒã³åºãã¯ããããã«ã¢ã¯ã»ã¹ããããã«
thisãšããŠã¿ãŒã²ãããªããžã§ã¯ãããã€å¿ èŠããããŸãã - ãªããžã§ã¯ãã®ç䟡è©äŸ¡
===ã¯ã€ã³ã¿ãŒã»ããã§ããŸããã - ããã©ãŒãã³ã¹: ãã³ãããŒã¯ã¯ãšã³ãžã³ã«ãããŸãããéåžžãæãåçŽãªãããã·ã䜿çšããããããã£ãžã®ã¢ã¯ã»ã¹ããã«ãæ°åæéãããããŸãããããå®éã«ãããåé¡ã«ãªãã®ã¯äžéšã® âããã«ããã¯â ãªããžã§ã¯ãã®ã¿ã§ãã
ã³ã¡ã³ã
<code>ã¿ã°ã䜿ã£ãŠãã ãããè€æ°è¡ã®å Žåã¯<pre>ãã10è¡ãè¶ ããå Žåã«ã¯ãµã³ãããã¯ã¹ã䜿ã£ãŠãã ãã(plnkr, JSBin, codepenâŠ)ã