ãã£ãã¿ã¼ ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ ã§å¦ãã éããJavaScriptã¨ã³ã¸ã³ã¯ããããå°éå¯è½ãª(ããã¦æ½å¨çã«å©ç¨ãããå¯è½æ§ããã)éãã¡ã¢ãªä¸ã«å¤ãä¿æãã¦ãã¾ãã
ä¾:
let john = { name: "John" };
// ãªãã¸ã§ã¯ãã¸ã¯ã¢ã¯ã»ã¹å¯è½ã§ããjohn ããã®åç
§ãæã£ã¦ãã¾ã
// åç
§ã䏿¸ããã¾ã
john = null;
// ãªãã¸ã§ã¯ãã¯ã¡ã¢ãªããåé¤ãããã§ããã
é常ããªãã¸ã§ã¯ãã¾ãã¯é åã®è¦ç´ ããããã¯å¥ã®ãã¼ã¿æ§é ã®ããããã£ã¯å°éå¯è½ã¨èãããããã®ãã¼ã¿æ§é ãã¡ã¢ãªã«ããéã¯ä¿æããç¶ãã¾ãã
ä¾ãã°ããããªãã¸ã§ã¯ããé åã«å ¥ããå ´åããã®é åãçãã¦ããéã¯ãä»ã®åç §ããªãã¦ããã®ãªãã¸ã§ã¯ãã¯çãã¦ãããã¨ã«ãªãã¾ãã
ä¾:
let john = { name: "John" };
let array = [ john ];
john = null; // åç
§ã䏿¸ããã¾ã
// 以å john ã§åç
§ããã¦ãããªãã¸ã§ã¯ãã¯é
åå
ã«æ ¼ç´ããã¦ãã¾ã
// ãã®ãããã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ããã¾ããã
// array[0] ã§åå¾ãããã¨ãå¯è½ã§ã
ã¾ããé常㮠Map ã®ãã¼ã¨ãã¦ãªãã¸ã§ã¯ãã使ãã¨ãMap ãåå¨ãã¦ããéã¯ãã®ãªãã¸ã§ã¯ããåå¨ãã¾ããããã¯ã¡ã¢ãªãå ããã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããªãããããã¾ããã
ä¾:
let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null; // åç
§ã䏿¸ããã¾ã
// john 㯠map ã®ä¸ã«ä¿æããã¦ãã¾ã
// map.keys() ã§åå¾ãããã¨ãã§ãã¾ã
WeakMap ã¯ãã®ç¹ã§æ ¹æ¬çã«ç°ãªãã¾ãããããã¯ãã¼ãªãã¸ã§ã¯ãã®ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã妨ãããã¨ã¯ããã¾ããã
ä¾ã§ãã®æå³ããã¨ãããè¦ã¦ããã¾ãããã
WeakMap
Map ã¨ã®æåã®éãã¯ãWeakMap ã®ãã¼ã¯ããªããã£ããªå¤ã§ã¯ãªããªãã¸ã§ã¯ãã§ãªããã°ãªããªããã¨ã§ã:
let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "ok"); // æ£å¸¸ã«åä½ãã¾ã (ãªãã¸ã§ã¯ãã®ãã¼)
// ãã¼ã«æååã¯ä½¿ãã¾ãã
weakMap.set("test", "Whoops"); // ã¨ã©ã¼, "test" ã¯ãªãã¸ã§ã¯ãã§ã¯ãªããã
ãã¾ããªãã¸ã§ã¯ãããã¼ã¨ãã¦ä½¿ç¨ãããã®ãªãã¸ã§ã¯ãã¸ã®åç §ãä»ã«ãªãå ´åãèªåçã«ã¡ã¢ãª(㨠map)ããåé¤ããã¾ãã
let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // åç
§ã䏿¸ããã¾ã
// john ã¯ã¡ã¢ãªããåé¤ããã¾ã!
ä¸ã®ä¾ãé常㮠Map ã®å ´åã¨æ¯ã¹ã¦è¦ã¦ãã ãããWeakMap ã®ãã¼ã¨ãã¦ã®ã¿ john ãåå¨ããå ´åãèªåçã«åé¤ããã¾ãã
WeakMap ã¯ç¹°ãè¿ãã¨ãã¡ã½ãã keys(), values(), entries() ããµãã¼ããã¾ããããã®ããããã¹ã¦ã®ãã¼ãå¤ãåå¾ããæ¹æ³ã¯ããã¾ããã
WeakMap ã¯æ¬¡ã®ã¡ã½ããã®ã¿ãæã£ã¦ãã¾ã:
weakMap.get(key)weakMap.set(key, value)weakMap.delete(key, value)weakMap.has(key)
ãªããã®ãããªå¶éãããã®ã§ããããï¼ããã¯æè¡çãªçç±ã§ãããããªãã¸ã§ã¯ãããã¹ã¦ã®ä»ã®åç
§ã失ã£ãå ´å(ä¸ã®ã³ã¼ãã® john ã®ããã«)ãèªåçã«åé¤ããã¾ããããããæè¡çã«ã¯ ãã¤ã¯ãªã¼ã³ã¢ãããçºçããã ã¯æ£ç¢ºã«ã¯æå®ããã¦ãã¾ããã
ããã¯JavaScriptã¨ã³ã¸ã³ã決å®ãã¾ããã¨ã³ã¸ã³ã¯ããã«ã¡ã¢ãªã®ã¯ãªã¼ã³ã¢ãããå®è¡ããããå¾
ã£ã¦ããå¤ãã®åé¤ãçºçããå¾ã«ã¯ãªã¼ã³ã¢ãããããã鏿ã§ãã¾ããå¾ã£ã¦ãæè¡çã«ã¯WeakMap ã®ç¾å¨ã®è¦ç´ æ°ã¯ãããã¾ãããã¨ã³ã¸ã³ãã¯ãªã¼ã³ã¢ãããã¦ãã/ãã¦ããªããã¾ãã¯é¨åçã«ããããã¦ããããããã¾ããããã®ãããªçç±ãããWeakMap å
¨ä½ã«ã¢ã¯ã»ã¹ããã¡ã½ããã¯ãµãã¼ãããã¦ãã¾ããã
ãã¦ãã©ãã§ãã®ãããªãã®ãå¿ è¦ãªã®ã§ãããï¼
ã¦ã¼ã¹ã±ã¼ã¹: additional data
WeakMap ã®ã¢ããªã±ã¼ã·ã§ã³ã®ä¸»ãªé åã¯ã 追å ã®ãã¼ã¿æ ¼ç´ ã§ãã
å¥ã®ã³ã¼ãããããããµã¼ããã¼ãã£ã©ã¤ãã©ãªã« âå±ããâ ãªãã¸ã§ã¯ããæä½ãã¦ãã¦ãããã«é¢é£ä»ãããããã¼ã¿ãããã¤ãä¿åãããå ´åãããã¯å
ã®ãªãã¸ã§ã¯ããçãã¦ããéã ãåå¨ãã¦ããå¿
è¦ãããã¾ãããã®ã¨ããWeakMap ã¯ã¾ãã«å¿
è¦ã¨ããããã®ã§ãã
ãã¼ã¨ãã¦ãªãã¸ã§ã¯ãã使ç¨ãã¦ãWeakMap ã«ãã¼ã¿ãæ ¼ç´ãããªãã¸ã§ã¯ããã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããã¨ãããã¼ã¿ãåæ§èªåçã«æ¶ãã¾ãã
weakMap.set(john, "secret documents");
// ãã john ããªããªã£ãå ´åãç§å¯ã®ããã¥ã¡ã³ãã¯ç ´å£ãããã§ããã
ä¾ãè¦ã¦ã¿ã¾ãããã
ä¾ãã°ãã¦ã¼ã¶ã®è¨ªåã«ã¦ã³ããä¿æããã³ã¼ããããã¨ãã¾ããæ å ±ã¯ map ã«ä¿æããã¦ãã¾ããã¦ã¼ã¶ãªãã¸ã§ã¯ãããã¼ã§ããã訪åã«ã¦ã³ãããã®å¤ã§ããã¦ã¼ã¶ãé¢ããã¨ãï¼ãã®ãªãã¸ã§ã¯ããã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããï¼ããããã®ã¦ã¼ã¶ã®è¨ªåã«ã¦ã³ãã¯ä¿æããå¿ è¦ã¯ããã¾ããã
ããã¯ã Map ã使ç¨ããã«ã¦ã³ã颿°ã®ä¾ã§ã:
// ð visitsCount.js
let visitsCountMap = new Map(); // map: user => visits count
// 訪åã«ã¦ã³ããå¢ãã
function countUser(user) {
let count = visitsCountMap.get(user) || 0;
visitsCountMap.set(user, count + 1);
}
ã¾ããããã¯ã³ã¼ãã®å¥ã®é¨åã§ãããããä¸ã®é¢æ°ã使ç¨ããå¥ã®ãã¡ã¤ã«ã§ã:
// ð main.js
let john = { name: "John" };
countUser(john); // 訪åãã«ã¦ã³ã
// ãã¨ã§ john ãé¢è±ããã¨ã
john = null;
ãã®ã¨ããjohn ãªãã¸ã§ã¯ãã¯ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãããã¹ãã§ãããvisitsCountMap ã®ãã¼ãªã®ã§ãã¡ã¢ãªã«æ®ã£ãã¾ã¾ã§ãã
ã¦ã¼ã¶ãåé¤ãããã¨ããvisitsCountMap ãã¯ãªã¼ã³ã¢ããããå¿
è¦ãããã¾ããããããªãã¨ãã¡ã¢ãªå
ã§ç¡éã«å¤§ãããªãã¾ãããã®ãããªã¯ãªã¼ãã³ã°ã¯è¤éãªã¢ã¼ããã¯ãã£ã§ã¯é¢åãªä½æ¥ã«ãªããã¾ãã
代ããã« WeakMap ã«åãæ¿ãããã¨ã§åé¿ã§ãã¾ã:
// ð visitsCount.js
let visitsCountMap = new WeakMap(); // weakmap: user => visits count
// è¨ªåæ°ãå¢å
function countUser(user) {
let count = visitsCountMap.get(user) || 0;
visitsCountMap.set(user, count + 1);
}
ããã§ãvisitsCountMap ãã¯ãªã¼ã³ã¢ããããå¿
è¦ã¯ããã¾ãããWeakMap ã®ãã¼ãé¤ãããã¹ã¦ã®ææ®µã§ john ãªãã¸ã§ã¯ããå°éä¸å¯è½ã«ãªã£ãå¾ãWeakMap ãããã®ãã¼ã«ããæ
å ±ã¨ã¨ãã«ãã¡ã¢ãªããã¯åé¤ããã¾ãã
ã¦ã¼ã¹ã±ã¼ã¹: ãã£ãã·ã¥
ããä¸ã¤ã®ä¸è¬çãªä¾ã¯ãã£ãã·ã¥ã§ãã颿°ããã®çµæãä¿æï¼âãã£ãã·ã¥âï¼ã§ããã®ã§ãåããªãã¸ã§ã¯ãã«å¯¾ããå°æ¥ã®å¼ã³åºãã§åå©ç¨ãããã¨ãã§ãã¾ãã
ãããå®ç¾ããããã«ãMapï¼æé©ã§ã¯ãªãã·ããªãªï¼ãå©ç¨ã§ãã¾ã:
// ð cache.js
let cache = new Map();
// è¨ç®ãçµæãè¦ãã
function process(obj) {
if (!cache.has(obj)) {
let result = obj /* ã«å¯¾ããè¨ç®çµæ */;
cache.set(obj, result);
}
return cache.get(obj);
}
// ããã§ãå¥ã®ãã¡ã¤ã«ã§ process() ã使ç¨ãã¾ãã
// ð main.js
let obj = {/* ãªãã¸ã§ã¯ããããã¨ãã¾ã */};
let result1 = process(obj); // è¨ç®ãã¾ã
// ...ãã®å¾ãå¥ã®å ´æã§å¼ã°ããã¨ãã¾ã...
let result2 = process(obj); // ãã£ãã·ã¥ããåå¾ãããè¨æ¶ãããçµæã使ããã¾ã
// ...å¾ã»ã©ããªãã¸ã§ã¯ãããã以ä¸ã¯ä¸è¦ã«ãªã£ãã¨ã
obj = null;
alert(cache.size); // 1 (ãªãã¨! ãªãã¸ã§ã¯ãã¯ä¾ç¶ã¨ãã¦ãã£ãã·ã¥ããã¦ãããã¡ã¢ãªãé£ã£ã¦ãã¾ã!)
åããªãã¸ã§ã¯ãã®ã§ process(obj) ã®è¤æ°åã®å¼ã³åºãã«å¯¾ãã¦ãååã ãçµæã®è¨ç®ãè¡ãããã®å¾ã¯ cache ããå¤ãåãã¾ãããã¡ãªããã¯ããªãã¸ã§ã¯ãããã以ä¸ä¸è¦ã«ãªã£ãã¨ããcache ã®ã¯ãªã¼ã³ã¢ãããå¿
è¦ãªãã¨ã§ãã
Map ã WeakMap ã«ç½®ãæããå ´åããã®åé¡ã¯æ¶ãã¾ãããã£ãã·ã¥ãããçµæã¯ãªãã¸ã§ã¯ãã®ã¬ãã¼ã¸ã³ã¬ã¯ãå¾ãèªåçã«ã¡ã¢ãªããåé¤ããã¾ãã
// ð cache.js
let cache = new WeakMap();
// è¨ç®ãçµæãè¦ãã
function process(obj) {
if (!cache.has(obj)) {
let result = obj /* ã«å¯¾ããè¨ç®çµæ */;
cache.set(obj, result);
}
return cache.get(obj);
}
// ð main.js
let obj = {/* some object */};
let result1 = process(obj);
let result2 = process(obj);
// ...å¾ã»ã©ããªãã¸ã§ã¯ãããã以ä¸ã¯ä¸è¦ã«ãªã£ãã¨ã
obj = null;
// WeakMap ãªã®ã§ cache.size ã¯åå¾ã§ãã¾ãã
// ãã0 ãããã¯ããã« 0 ã«ãªãã¾ã
// ãªãã¸ã§ã¯ããã¬ãã¼ã¸ã³ã¬ã¯ããããã¨ããã£ãã·ã¥ããããã¼ã¿ãåæ§ã«åé¤ããã¾ãã
WeakSet
WeakSet ãåæ§ã«åä½ãã¾ã:
Setã«ä¼¼ã¦ãã¾ãããWeakSetã¸ã¯ãªãã¸ã§ã¯ãã®ã¿è¿½å ã§ãã¾ãï¼ããªããã£ãã§ã¯ããã¾ããï¼- ãªãã¸ã§ã¯ãã¯ãå¥ã®å ´æããå°éå¯è½ã§ããéã
Setã«åå¨ãã¾ãã Setåæ§ãadd,has,deleteããµãã¼ããã¾ãããsize,keys()ã¨ã¤ãã¬ã¼ã·ã§ã³ã¯ãµãã¼ããã¾ããã
âå¼±ãâ ã®ã§ã追å ã®æ ¼ç´å ´æã¨ãã¦ã使ãã¾ããã§ãããä»»æã®ãã¼ã¿ã§ã¯ãªããããã âã¯ã/ãããâ ã¨ãã boolean ã©ã¤ã¯ãªæ
å ±ãè¨æ¶ããããã®ãã®ã¨ãã¦ã§ããWeakSet ã®ã¡ã³ãã¼ã¯ãªãã¸ã§ã¯ãã«ã¤ãã¦ãªã«ããæå³ããå ´åãããã¾ãã
ä¾ãã°ãã¦ã¼ã¶ã WeakSet ã«è¿½å ãã¦ããµã¤ãã«ã¢ã¯ã»ã¹ããã¦ã¼ã¶ã追跡ã§ãã¾ãã:
let visitedSet = new WeakSet();
let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };
visitedSet.add(john); // John ã訪å
visitedSet.add(pete); // 次㫠Pete
visitedSet.add(john); // John åã³
// visitedSet 㯠2 ã¦ã¼ã¶ãã¾ã
// John ã訪åãããã©ããããã§ãã¯
alert(visitedSet.has(john)); // true
// Mary ã訪åãããããã§ãã¯
alert(visitedSet.has(mary)); // false
john = null;
// visitedSet ã¯èªåçã«ã¯ãªã¼ã³ã¢ããããã¾ãã
æã注ç®ãã¹ã WeakMap 㨠WeakSet ã®å¶éã¯ãã¤ãã¬ã¼ã·ã§ã³ã®æ¬ å¦ã¨ç¾å¨ã®ãã¹ã¦ã®ã³ã³ãã³ããåå¾ãããã¨ãã§ããªããã¨ã§ããããã¯ä¸ä¾¿ã«è¦ããããããã¾ããããWeakMap/WeakSet ããããã®ä¸»è¦ãªã¸ã§ã â å¥ã®å ´æã«ä¿å/管çããã¦ãããªãã¸ã§ã¯ãã®ãã¼ã¿ã® â追å ã®â ä¿ç®¡å ´æã«ãªãã㨠â ãããã®ã妨ãããã¨ã¯ããã¾ããã
ãµããª
WeakMap 㯠Map ã©ã¤ã¯ãªã³ã¬ã¯ã·ã§ã³ã§ããããªãã¸ã§ã¯ãã®ã¿ããã¼ã¨ãã¦è¨±å¯ãããä»ã®ææ®µã§ãã®ãªãã¸ã§ã¯ããå°éä¸å¯è½ã«ãªãã¨ãé¢é£ä»ããããå¤ã¨ä¸ç·ã«åé¤ããã¾ãã
WeakSet 㯠Set ã©ã¤ã¯ãªã³ã¬ã¯ã·ã§ã³ã§ããããªãã¸ã§ã¯ãã®ã¿ãä¿ç®¡ã§ããä»ã®ææ®µã§ãã®ãªãã¸ã§ã¯ããå°éä¸å¯è½ã«ãªãã¨ãããããåé¤ããã¾ãã
ãããã®ä¸»ãªã¢ããã³ãã¼ã¸ã¯ããªãã¸ã§ã¯ãã«å¯¾ãã¦å¼±ãåç §ãæã£ã¦ãããã¨ã§ãããªã®ã§ãã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã§å®¹æã«åé¤ã§ãã¾ãã
ãªããããã«ã¯ clear, size, keys, values ãªã©ã®ãµãã¼ãããªãã¨ãã代åãä¼´ãã¾ãã
WeakMap 㨠WeakSet 㯠â主è¦ãªâ ãªãã¸ã§ã¯ãä¿ç®¡å ´æã«å ããâ2ã¤ç®ã®â ãã¼ã¿æ§é ã¨ãã¦ä½¿ç¨ããã¾ãã䏿¦ãªãã¸ã§ã¯ãã主è¦ãªä¿ç®¡å ´æããåé¤ãããã¨ãããã WeakMap ã®ãã¼ã¾ã㯠WeakSet ã§ã®ã¿è¦ã¤ãã£ãå ´åããªãã¸ã§ã¯ãã¯èªåçã«ã¯ãªã¼ã³ã¢ããããã¾ãã
ã³ã¡ã³ã
<code>ã¿ã°ã使ã£ã¦ãã ãããè¤æ°è¡ã®å ´åã¯<pre>ãã10è¡ãè¶ ããå ´åã«ã¯ãµã³ãããã¯ã¹ã使ã£ã¦ãã ãã(plnkr, JSBin, codepenâ¦)ã