WeakMap
Baseline
åºãå©ç¨å¯è½
*
ãã®æ©è½ã¯åºãå®è£ ããã¦ãããå¤ãã®ãã¼ã¸ã§ã³ã®ç«¯æ«ããã©ã¦ã¶ã¼ã§åä½ãã¾ãã2015å¹´7æä»¥éããã¹ã¦ã®ãã©ã¦ã¶ã¼ã§å©ç¨å¯è½ã§ãã
* ãã®æ©è½ã®ä¸é¨ã¯ã対å¿ã¬ãã«ãç°ãªãå ´åãããã¾ãã
WeakMap ã¯ãã¼ã¨å¤ã®çµã®éåã§ããããã¼ã¯ãªãã¸ã§ã¯ãã¾ãã¯éç»é²ã·ã³ãã«ã§ãªããã°ãªãããå¤ã¯ä»»æã® JavaScript åã§ããã¼ã¸ã®å¼·ãåç
§ãçæãã¾ãããã¤ã¾ããWeakMap å
ã®ãã¼ã¨ãã¦ã®ãªãã¸ã§ã¯ããåå¨ãã¦ãããã®ãªãã¸ã§ã¯ããã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããå¯è½æ§ãããã¾ãããã¼ã¨ãã¦ä½¿ç¨ããããªãã¸ã§ã¯ããååãããã¨ããã®ãªãã¸ã§ã¯ãã«å¯¾å¿ããå¤ã¯ãä»ã®å ´æã§å¼·ãåç
§ããã¦ããªãéããã©ã® WeakMap ã«ããã¦ãåæ§ã«ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã®å¯¾è±¡ã¨ãªãã¾ããWeakMap ã®ãã¼ã¨ãã¦ä½¿ç¨ãããã¨ãã§ããå¯ä¸ã®ããªããã£ãåã¯ã·ã³ãã«ï¼æ£ç¢ºã«è¨ãã°ãéç»é²ã·ã³ãã«ï¼ã§ããéç»é²ã·ã³ãã«ã¯ä¸ææ§ãä¿è¨¼ãããåçæãããªãããã§ãã
WeakMapã¯ãå¤ããã¼ãåç
§ãã¦ããå ´åã§ãããã¼ã¨ãªããªãã¸ã§ã¯ããã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããã®ã妨ããªãæ¹æ³ã§ããã¼ã¿ã¨ãªãã¸ã§ã¯ããé¢é£ä»ãããã¨ãã§ãã¾ãããã ããWeakMapã¯ãã¼ã®çåç¶æ
ãç£è¦ã§ããªããããåæããããã¨ãã§ãã¾ãããWeakMap ããã¼ãåæããã¡ã½ãããå
¬éããå ´åããã®ãªã¹ãã¯ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã®ç¶æ
ã«ä¾åãããããä¸ç¢ºå®æ§ãçãã¾ãããã¼ã®åæãè¡ãããã®ã§ããã°ãWeakMap ã§ã¯ãªã Map ã使ç¨ãã¦ãã ããã
WeakMap ã«ã¤ãã¦è©³ããç¥ãã«ã¯ã WeakMap ãªãã¸ã§ã¯ãã®ã¬ã¤ãï¼ãã¼ä»ãã³ã¬ã¯ã·ã§ã³å
ï¼ãåç
§ãã¦ãã ããã
解説
WeakMap ã®ãã¼ã¯ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³å¯è½ã§ãªããã°ãªãã¾ãããã»ã¨ãã©ã®ããªããã£ããã¼ã¿åã¯ä»»æã«ä½æã§ãã寿å½ãæããªãããããã¼ã¨ãã¦ä½¿ç¨ã§ãã¾ããããªãã¸ã§ã¯ãã¨éç»é²ã·ã³ãã«ã¯ãã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³å¯è½ã§ãããããã¼ã¨ãã¦ä½¿ç¨ã§ãã¾ãã
ãã¼ã®ç価æ§
é常㮠Map ã¨åæ§ã«ãå¤ã®ç価æ§ã¯ SameValueZero ã¢ã«ã´ãªãºã ã«åºã¥ãã¾ãããã㯠=== æ¼ç®åã¨åãã§ããWeakMap ããªãã¸ã§ã¯ãã¨ã·ã³ãã«ã®ãã¼ããä¿æã§ããªãããã§ããã¤ã¾ãããªãã¸ã§ã¯ããã¼ã®å ´åãç価æ§ã¯ãªãã¸ã§ã¯ããåä¸ã®ãã®ã§ãããã«åºã¥ãã¾ãããããã¯å¤ã§ã¯ãªãåç
§ã«ãã£ã¦æ¯è¼ããã¾ãã
ãªã WeakMap ãªã®ã
ããã API ã¯ã4 ã¤ã® API ã¡ã½ããã§å ±æããã 2 ã¤ã®é åï¼1 ã¤ã¯ãã¼ç¨ããã 1 ã¤ã¯å¤ç¨ï¼ãç¨ãããã¨ã§ãJavaScript ã«å®è£ ãããã¨ãã§ãã¾ããããã®ãããã«è¦ç´ ãè¨å®ããã¨ãããããã®é åã®æå¾ã«åæã«ãã¼ã¨å¤ã追å ãããã¨ã«ãªãã¾ãããã®çµæã両æ¹ã®é åã§ãã¼ã¨å¤ã®ã¤ã³ããã¯ã¹ã¯å¯¾å¿ãã¨ãã¦ãã¾ãããããããå¤ãåå¾ããã«ã¯ããã¹ã¦ã®ãã¼ãæä½ãã¦ä¸è´ãããã®ãè¦ã¤ããè¦ã¤ãã£ããã¼ã®ã¤ã³ããã¯ã¹ã使ç¨ãã¦å¤ã®é åãã対å¿ããå¤ãåãåºãã¾ãã
ããããå®è£ ã§ã¯ã主㫠2 ã¤ã®ä¸é½åãçãããã¨ã¨ãªãã¾ãã
- 第ä¸ã«ãè¨å®ãæ¢ç´¢ã®è¨ç®éã
O(n)ã¨ãªãã㨠(n ã¯ãããä¸ã«ããããã¼ã®æ°) ã§ãã©ã¡ãã®æä½ãä¸è´ããå¤ãè¦ã¤ããããã«ãã¼ã®ãªã¹ããèµ°æ»ããªããã°ãªããªãããã§ãã - 第äºã®ä¸é½åã¯ãé åãåãã¼ã¨åå¤ã¸ã®åç §ãç¡æéã«ç¶æãããã¨ãä¿è¨¼ãã¦ãããããã¡ã¢ãªã¼ãªã¼ã¯ãçºçãããã¨ã§ãããããã®åç §ã¯ããªãã¸ã§ã¯ãã¸ã®ä»ã®åç §ããªãå ´åã§ãããã¼ãã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããã®ãé²ãã¾ããããã«ããã対å¿ããå¤ãã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããã®ãé²ããã¨ã«ããªãã¾ãã
ããã«å¯¾ããWeakMap ã§ã¯ããã¼ãªãã¸ã§ã¯ãã¯ããã®ãã¼ãã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããªãéãããã®ã³ã³ãã³ãã«å¯¾ãã¦å¼·ãåç
§ãã¾ããããã®å¾ã¯å¼±ãåç
§ãã¾ãããããã£ã¦ãWeakMap ã¯æ¬¡ã®ããã«åä½ãã¾ãã
- ãã¼ãªãã¸ã§ã¯ãã¸ã®åç §ãæçµçã«é¤å»ãããã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã妨ãã¾ããã
WeakMap以å¤ã®å ´æããåç §ããã¦ããªããã¼ãªãã¸ã§ã¯ããæã¤å¤ã¯ãã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã®å¯¾è±¡ã¨ãªããã¨ãããã¾ãã
WeakMap ã¯ããã¼ãã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ããã¦ããªãå ´åã«ã®ã¿æçãªããã¼ã«é¢ããæ
å ±ããã¼ã«å²ãå½ã¦ãéã«ç¹ã«æçãªãã¼ã¿æ§é ã§ãã
ããããWeakMapã¯ãã¼ã®çåç¶æ
ãç£è¦ã§ããªãããããã¼ã¯åæå¯è½ã§ã¯ããã¾ããããã¼ã®ãªã¹ããåå¾ããã¡ã½ããã¯åå¨ãã¾ãããä»®ã«åå¨ããå ´åããã®ãªã¹ãã¯ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã®ç¶æ
ã«ä¾åããä¸ç¢ºå®æ§ãçãããã¨ã«ãªãã¾ãããã¼ã®ãªã¹ããå¿
è¦ãªå ´åã¯ã Map ã使ç¨ãã¦ãã ããã
ã³ã³ã¹ãã©ã¯ã¿ã¼
WeakMap()-
æ°ãã
WeakMapãªãã¸ã§ã¯ããçæãã¾ãã
ã¤ã³ã¹ã¿ã³ã¹ããããã£
ãããã®ããããã£ã¯ WeakMap.prototype ã«å®ç¾©ããããã¹ã¦ã® WeakMap ã¤ã³ã¹ã¿ã³ã¹ã§å
±æããã¾ãã
WeakMap.prototype.constructor-
ãã®ã¤ã³ã¹ã¿ã³ã¹ãªãã¸ã§ã¯ãã使ããã³ã³ã¹ãã©ã¯ã¿ã¼é¢æ°ã
WeakMapã¤ã³ã¹ã¿ã³ã¹ã®å ´åãåæå¤ã¯WeakMapã³ã³ã¹ãã©ã¯ã¿ã¼ã§ãã WeakMap.prototype[Symbol.toStringTag]-
[Symbol.toStringTag]ããããã£ã®åæå¤ã¯æåå"WeakMap"ã§ãããã®ããããã£ã¯Object.prototype.toString()ã§ä½¿ç¨ããã¾ãã
ã¤ã³ã¹ã¿ã³ã¹ã¡ã½ãã
WeakMap.prototype.delete()-
keyã«é¢é£ããå¤ãåé¤ãã¾ãããã®å¾WeakMap.prototype.has(key)ã¯falseãè¿ãã¾ãã WeakMap.prototype.get()-
keyã«é¢é£ããå¤ãè¿ãã¾ããè¦ã¤ãããªãå ´åãundefinedãè¿ãã¾ãã WeakMap.prototype.getOrInsert()-
ãã®
WeakMapå ã§æå®ããããã¼ã«å¯¾å¿ããå¤ãè¿ãã¾ãããã¼ãåå¨ããªãå ´åãæå®ãããããã©ã«ãå¤ãæã¤æ°ããé ç®ãæ¿å ¥ããæ¿å ¥ãããå¤ãè¿ãã¾ãã WeakMap.prototype.getOrInsertComputed()-
ãã®
WeakMapã§æå®ããããã¼ã«å¯¾å¿ããå¤ãè¿ãã¾ãããã¼ãåå¨ããªãå ´åãæå®ããããã¼ã¨ãä¸ããããã³ã¼ã«ããã¯ããè¨ç®ãããããã©ã«ãå¤ãæã¤æ°ããé ç®ãæ¿å ¥ããæ¿å ¥ãããå¤ãè¿ãã¾ãã WeakMap.prototype.has()-
ãã®
WeakMapãªãã¸ã§ã¯ãå ã«ãæå®ããããã¼ã«é¢é£ä»ããããå¤ããããã©ãã示ãè«çå¤ãè¿ãã¾ãã WeakMap.prototype.set()-
ãã®
WeakMapãªãã¸ã§ã¯ãå ã«ãæå®ããããã¼ã¨å¤ãæã¤æ°ããé ç®ã追å ãã¾ãããã§ã«ãã®ãã¼ãåå¨ããå ´åã¯ãæ¢åã®é ç®ãæ´æ°ãã¾ãã
ä¾
>WeakMap ã®ä½¿ç¨
const wm1 = new WeakMap();
const wm2 = new WeakMap();
const wm3 = new WeakMap();
const o1 = {};
const o2 = () => {};
const o3 = window;
wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // å¤ã¯ï¼ãªãã¸ã§ã¯ãã¾ãã¯é¢æ°ãå«ãï¼ä½ã§ãã£ã¦ããã¾ãã¾ãã
wm2.set(o2, undefined);
wm2.set(wm1, wm2); // ãã¼ãå¤ãã©ããªãªãã¸ã§ã¯ãã§ããã¾ãã¾ããã WeakMap ã§ãã£ã¦ãããã®ã§ãï¼
wm1.get(o2); // "azerty"
wm2.get(o2); // undefined ãè¨å®ããã¦ããã®ã§ undefined
wm2.get(o3); // o3 ã®ãã¼ã wm2 ã«åå¨ããªãã®ã§ undefined
wm1.has(o2); // true
wm2.has(o2); // trueï¼å¤èªä½ã 'undefied' ãã£ã¦ãï¼
wm2.has(o3); // false
wm3.set(o1, 37);
wm3.get(o1); // 37
wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false
.clear() ã¡ã½ãããæã¤ WeakMap 風ã®ã¯ã©ã¹ã®å®è£
class ClearableWeakMap {
#wm;
constructor(init) {
this.#wm = new WeakMap(init);
}
clear() {
this.#wm = new WeakMap();
}
delete(k) {
return this.#wm.delete(k);
}
get(k) {
return this.#wm.get(k);
}
has(k) {
return this.#wm.has(k);
}
set(k, v) {
this.#wm.set(k, v);
return this;
}
}
ãã©ã¤ãã¼ãã¡ã³ãã¼ã®ã¨ãã¥ã¬ã¼ã·ã§ã³
éçºè
ã¯WeakMapã使ç¨ãã¦ãªãã¸ã§ã¯ãã«ãã©ã¤ãã¼ããã¼ã¿ãé¢é£ä»ãããã¨ãã§ããããã«ã¯æ¬¡ã®ãããªå©ç¹ãããã¾ãã
Mapã¨æ¯ã¹ãã¨ãWeakMap ã¯ãã¼ã¨ãã¦ä½¿ç¨ããããªãã¸ã§ã¯ãã¸ã®å¼·ãåç §ãä¿æããªããããã¡ã¿ãã¼ã¿ã®åç¶æéããªãã¸ã§ã¯ãèªä½ã¨åãã«ãªããã¡ã¢ãªã¼ãªã¼ã¯ãé¿ãããã¨ãã§ãã¾ãã- åæä¸å¯è½ããããã£ã
Symbolããããã£ã使ç¨ããå ´åã¨æ¯ã¹ãWeakMap ã¯ãªãã¸ã§ã¯ãã®å¤é¨ã«åå¨ãããããã¦ã¼ã¶ã¼ã³ã¼ããObject.getOwnPropertySymbolsã®ãããªåå°ã¡ã½ãããéãã¦ã¡ã¿ãã¼ã¿ãåå¾ããæ¹æ³ãããã¾ããã - ã¯ãã¼ã¸ã£ã¨æ¯ã¹ãã¨ãåã WeakMap ãã³ã³ã¹ãã©ã¯ã¿ã¼ããçæããããã¹ã¦ã®ã¤ã³ã¹ã¿ã³ã¹ã§åå©ç¨ã§ãããããã¡ã¢ãªã¼å¹çãåä¸ãã¾ããã¾ããåãã¯ã©ã¹ã®ç°ãªãã¤ã³ã¹ã¿ã³ã¹ãäºãã®ãã©ã¤ãã¼ãã¡ã³ãã¼ãèªã¿åããã¨ãã§ãã¾ãã
let Thing;
{
const privateScope = new WeakMap();
let counter = 0;
Thing = function () {
this.someProperty = "foo";
privateScope.set(this, {
hidden: ++counter,
});
};
Thing.prototype.showPublic = function () {
return this.someProperty;
};
Thing.prototype.showPrivate = function () {
return privateScope.get(this).hidden;
};
}
console.log(typeof privateScope);
// "undefined"
const thing = new Thing();
console.log(thing);
// Thing {someProperty: "foo"}
thing.showPublic();
// "foo"
thing.showPrivate();
// 1
ããã¯ããã©ã¤ãã¼ããã£ã¼ã«ãã使ç¨ããæ¬¡ã®ã³ã¼ãã¨ã»ã¼åçã§ãã
class Thing {
static #counter = 0;
#hidden;
constructor() {
this.someProperty = "foo";
this.#hidden = ++Thing.#counter;
}
showPublic() {
return this.someProperty;
}
showPrivate() {
return this.#hidden;
}
}
console.log(thing);
// Thing {someProperty: "foo"}
thing.showPublic();
// "foo"
thing.showPrivate();
// 1
ã¡ã¿ãã¼ã¿ã®é¢é£ä»ã
WeakMapã¯ããªãã¸ã§ã¯ãèªä½ã®åç¶æéã«å½±é¿ãä¸ããã«ããªãã¸ã§ã¯ãã«ã¡ã¿ãã¼ã¿ãé¢é£ä»ããããã«ä½¿ç¨ã§ãã¾ããããã¯ãã©ã¤ãã¼ãã¡ã³ãã¼ã®ä¾ã¨é常ã«ä¼¼ã¦ãã¾ãããã©ã¤ãã¼ãã¡ã³ãã¼ãã¾ãããããã¿ã¤ãç¶æ¿ã«åå ããªãå¤é¨ã¡ã¿ãã¼ã¿ã¨ãã¦ã¢ãã«åãããããã§ãã
ãã®ä½¿ãæ¹ã¯ãæ¢ã«çæããããªãã¸ã§ã¯ãã«ãæ¡å¼µã§ãã¾ããä¾ãã°ãã¦ã§ãä¸ã§ã¯ãDOM è¦ç´ ã«è¿½å ãã¼ã¿ãé¢é£ä»ããå¾ã§ãã® DOM è¦ç´ ãã¢ã¯ã»ã¹ã§ããããã«ãããå ´åãããã¾ããä¸è¬çãªææ³ã¯ããã¼ã¿ãããããã£ã¨ãã¦æ·»ä»ãããã¨ã§ãã
const buttons = document.querySelectorAll(".button");
buttons.forEach((button) => {
button.clicked = false;
button.addEventListener("click", () => {
button.clicked = true;
const currentButtons = [...document.querySelectorAll(".button")];
if (currentButtons.every((button) => button.clicked)) {
console.log("ãã¹ã¦ã®ãã¿ã³ãã¯ãªãã¯ããã¾ããï¼");
}
});
});
ãã®ã¢ããã¼ãã¯æå¹ã§ãããããã¤ãè½ã¨ãç©´ãããã¾ãã
clickedããããã£ã¯åæå¯è½ã§ãããããObject.keys(button)ãfor...inã«ã¼ããªã©ã§å¯¾è±¡ã¨ãã¦æ±ããã¾ãããã®åé¡ã¯Object.defineProperty()ã使ç¨ãããã¨ã§è»½æ¸ã§ãã¾ãããã³ã¼ããåé·ã«ãªãã¾ããclickedããããã£ã¯éå¸¸ã®æååããããã£ã§ãããããä»ã®ã³ã¼ãããã¢ã¯ã»ã¹ããã³ä¸æ¸ããå¯è½ã§ãããã®åé¡ã¯Symbolãã¼ã使ç¨ãããã¨ã§è»½æ¸ã§ãã¾ããããã®ãã¼ãObject.getOwnPropertySymbols()çµç±ã§ã¢ã¯ã»ã¹å¯è½ã¨ãªãã¾ãã
WeakMap ã使ç¨ãã¦ããããä¿®æ£ãã¦ã¿ã¾ãã
const buttons = document.querySelectorAll(".button");
const clicked = new WeakMap();
buttons.forEach((button) => {
clicked.set(button, false);
button.addEventListener("click", () => {
clicked.set(button, true);
const currentButtons = [...document.querySelectorAll(".button")];
if (currentButtons.every((button) => clicked.get(button))) {
console.log("ãã¹ã¦ã®ãã¿ã³ãã¯ãªãã¯ããã¾ããï¼");
}
});
});
ããã§ã¯ãclicked ã«ã¢ã¯ã»ã¹ã§ããã³ã¼ãã®ã¿ãããããã®ãã¿ã³ã®ã¯ãªãã¯ç¶æ
ãææ¡ãã¦ãããå¤é¨ã³ã¼ãã¯ç¶æ
ã夿´ã§ãã¾ãããããã«ãããããã®ãã¿ã³ã DOM ããé¤å»ãããã¨ãé¢é£ä»ããããã¡ã¿ãã¼ã¿ã¯èªåçã«ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã®å¯¾è±¡ã¨ãªãã¾ãã
ãã£ãã·ã¥
颿°ã«æ¸¡ããããªãã¸ã§ã¯ãã颿°ã®çµæã«é¢é£ä»ãããã¨ãã§ãã¾ããããã«ãããåããªãã¸ã§ã¯ããå度渡ãããå ´åã颿°ãåå®è¡ããã«ãã£ãã·ã¥ãããçµæãè¿ããã¨ãå¯è½ã§ãããã®æ©è½ã¯ã颿°ãç´ç²ï¼ã¤ã¾ããå¤é¨ãªãã¸ã§ã¯ãã夿´ãããä»ã®è¦³æ¸¬å¯è½ãªå¯ä½ç¨ãå¼ãèµ·ããããããªãï¼ã§ããå ´åã«æç¨ã§ãã
const cache = new WeakMap();
function handleObjectValues(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const result = Object.values(obj).map(heavyComputation);
cache.set(obj, result);
return result;
}
ãã®æ¹æ³ã¯ã颿°ã®å
¥åããªãã¸ã§ã¯ãã§ããå ´åã«ã®ã¿æå¹ã§ããããã«ãå
¥åãäºåº¦ã¨æ¸¡ãããªãã¦ãããã¼ï¼å
¥åï¼ãåç¶ãã¦ããéããçµæã¯ãã£ãã·ã¥ã«æ°¸ä¹
ã«æ®ãã¾ãããã广çãªæ¹æ³ã¯ãMap 㨠WeakRef ãªãã¸ã§ã¯ããçµã¿åããã¦ä½¿ç¨ãããã¨ã§ããããã«ãããããããåã®å
¥åå¤ããããã«å¯¾å¿ããï¼æ½å¨çã«å¤§è¦æ¨¡ãªï¼è¨ç®çµæã«é¢é£ä»ãããã¨ãã§ããããã«ãªãã¾ãã詳細㯠WeakRef 㨠FinalizationRegistry ã®ä¾ãåç
§ãã¦ãã ããã
仿§æ¸
| 仿§æ¸ |
|---|
| ECMAScript® 2027 Language Specification > # sec-weakmap-objects > |