æä»¬ä»åé¢ç åå¾åæ¶ ç« èä¸ç¥éï¼JavaScript 弿å¨å¼âå¯è¾¾âåå¯è½è¢«ä½¿ç¨æ¶ä¼å°å ¶ä¿æå¨å åä¸ã
ä¾å¦ï¼
let john = { name: "John" };
// 该对象è½è¢«è®¿é®ï¼john æ¯å®çå¼ç¨
// è¦çå¼ç¨
john = null;
// 该对象å°ä¼è¢«ä»å
å䏿¸
é¤
é常ï¼å½å¯¹è±¡ãæ°ç»ä¹ç±»çæ°æ®ç»æå¨å å䏿¶ï¼å®ä»¬çåå ç´ ï¼å¦å¯¹è±¡ç屿§ãæ°ç»çå ç´ é½è¢«è®¤ä¸ºæ¯å¯è¾¾çã
ä¾å¦ï¼å¦ææä¸ä¸ªå¯¹è±¡æ¾å ¥å°æ°ç»ä¸ï¼é£ä¹åªè¦è¿ä¸ªæ°ç»åå¨ï¼é£ä¹è¿ä¸ªå¯¹è±¡ä¹å°±åå¨ï¼å³ä½¿æ²¡æå ¶ä»å¯¹è¯¥å¯¹è±¡çå¼ç¨ã
å°±åè¿æ ·:
let john = { name: "John" };
let array = [ john ];
john = null; // è¦çå¼ç¨
// åé¢ç± john æå¼ç¨çé£ä¸ªå¯¹è±¡è¢«åå¨å¨äº array ä¸
// æä»¥å®ä¸ä¼è¢«åå¾åæ¶æºå¶åæ¶
// æä»¬å¯ä»¥éè¿ array[0] è·åå°å®
类似çï¼å¦ææä»¬ä½¿ç¨å¯¹è±¡ä½ä¸ºå¸¸è§ Map çé®ï¼é£ä¹å½ Map å卿¶ï¼è¯¥å¯¹è±¡ä¹å°åå¨ãå®ä¼å ç¨å
åï¼å¹¶ä¸ä¸ä¼è¢«ï¼åå¾åæ¶æºå¶ï¼åæ¶ã
ä¾å¦ï¼
let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null; // è¦çå¼ç¨
// john 被åå¨å¨äº map ä¸ï¼
// æä»¬å¯ä»¥ä½¿ç¨ map.keys() æ¥è·åå®
WeakMap å¨è¿æ¹é¢æçæ ¹æ¬ä¸çä¸åãå®ä¸ä¼é»æ¢åå¾åæ¶æºå¶å¯¹ä½ä¸ºé®ç对象ï¼key objectï¼çåæ¶ã
让æä»¬éè¿ä¾åæ¥ççè¿æçå°åºæ¯ä»ä¹ã
WeakMap
WeakMap å Map ç第ä¸ä¸ªä¸åç¹å°±æ¯ï¼WeakMap çé®å¿
é¡»æ¯å¯¹è±¡ï¼ä¸è½æ¯åå§å¼ï¼
let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "ok"); // æ£å¸¸å·¥ä½ï¼ä»¥å¯¹è±¡ä½ä¸ºé®ï¼
// ä¸è½ä½¿ç¨å符串ä½ä¸ºé®
weakMap.set("test", "Whoops"); // Errorï¼å 为 "test" 䏿¯ä¸ä¸ªå¯¹è±¡
ç°å¨ï¼å¦ææä»¬å¨ weakMap ä¸ä½¿ç¨ä¸ä¸ªå¯¹è±¡ä½ä¸ºé®ï¼å¹¶ä¸æ²¡æå ¶ä»å¯¹è¿ä¸ªå¯¹è±¡çå¼ç¨ ââ 该对象å°ä¼è¢«ä»å åï¼åmapï¼ä¸èªå¨æ¸ é¤ã
let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // è¦çå¼ç¨
// john 被ä»å
åä¸å é¤äºï¼
ä¸ä¸é¢å¸¸è§ç Map çä¾åç¸æ¯ï¼ç°å¨å¦æ john ä»
ä»
æ¯ä½ä¸º WeakMap çé®èåå¨ ââ å®å°ä¼è¢«ä» mapï¼åå
åï¼ä¸èªå¨å é¤ã
WeakMap 䏿¯æè¿ä»£ä»¥å keys()ï¼values() å entries() æ¹æ³ãæä»¥æ²¡æåæ³è·å WeakMap çææé®æå¼ã
WeakMap åªæä»¥ä¸çæ¹æ³ï¼
weakMap.get(key)weakMap.set(key, value)weakMap.delete(key)weakMap.has(key)
为ä»ä¹ä¼æè¿ç§éå¶å¢ï¼è¿æ¯ææ¯çåå ã妿ä¸ä¸ªå¯¹è±¡ä¸¢å¤±äºå
¶å®ææå¼ç¨ï¼å°±åä¸é¢ç¤ºä¾ä¸ç johnï¼ï¼é£ä¹å®å°±ä¼è¢«åå¾åæ¶æºå¶èªå¨åæ¶ã使¯å¨ä»ææ¯çè§åº¦å¹¶ä¸è½åç¡®ç¥é 使¶ä¼è¢«åæ¶ã
è¿äºé½æ¯ç± JavaScript 弿å³å®çãJavaScript 弿å¯è½ä¼éæ©ç«å³æ§è¡å
忏
çï¼å¦æç°å¨æ£å¨åçå¾å¤å 餿ä½ï¼é£ä¹ JavaScript 弿å¯è½å°±ä¼éæ©çä¸çï¼ç¨ååè¿è¡å
忏
çãå æ¤ï¼ä»ææ¯ä¸è®²ï¼WeakMap çå½åå
ç´ çæ°éæ¯æªç¥çãJavaScript 弿å¯è½æ¸
çäºå
¶ä¸çåå¾ï¼å¯è½æ²¡æ¸
çï¼ä¹å¯è½æ¸
çäºä¸é¨åãå æ¤ï¼æä¸æ¯æè®¿é® WeakMap çææé®/å¼çæ¹æ³ã
é£ä¹ï¼å¨åªéæä»¬ä¼éè¦è¿æ ·çæ°æ®ç»æå¢ï¼
ä½¿ç¨æ¡ä¾ï¼é¢å¤çæ°æ®
WeakMap ç主è¦åºç¨åºæ¯æ¯ é¢å¤æ°æ®çåå¨ã
å妿们æ£å¨å¤çä¸ä¸ªâå±äºâå¦ä¸ä¸ªä»£ç çä¸ä¸ªå¯¹è±¡ï¼ä¹å¯è½æ¯ç¬¬ä¸æ¹åºï¼å¹¶æ³åå¨ä¸äºä¸ä¹ç¸å
³çæ°æ®ï¼é£ä¹è¿äºæ°æ®å°±åºè¯¥ä¸è¿ä¸ªå¯¹è±¡å
±å亡 ââ è¿æ¶å WeakMap æ£æ¯æä»¬æéè¦çå©å¨ã
æä»¬å°è¿äºæ°æ®æ¾å° WeakMap ä¸ï¼å¹¶ä½¿ç¨è¯¥å¯¹è±¡ä½ä¸ºè¿äºæ°æ®çé®ï¼é£ä¹å½è¯¥å¯¹è±¡è¢«åå¾åæ¶æºå¶åæ¶åï¼è¿äºæ°æ®ä¹ä¼è¢«èªå¨æ¸
é¤ã
weakMap.set(john, "secret documents");
// 妿 john æ¶å¤±ï¼secret documents å°ä¼è¢«èªå¨æ¸
é¤
让æä»¬æ¥çä¸ä¸ªä¾åã
ä¾å¦ï¼æä»¬æç¨äºå¤çç¨æ·è®¿é®è®¡æ°ç代ç ãæ¶éå°çä¿¡æ¯è¢«åå¨å¨ 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); // count his visits
// ä¸ä¹
ä¹åï¼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 äºãå½ john 对象åæä¸å¯è¾¾æ¶ï¼å³ä¾¿å®æ¯ WeakMap éçä¸ä¸ªé®ï¼å®ä¹ä¼è¿åå®ä½ä¸º WeakMap éç鮿坹åºçä¿¡æ¯ä¸å被ä»å
åä¸å é¤ã
ä½¿ç¨æ¡ä¾ï¼ç¼å
å¦å¤ä¸ä¸ªå¸¸è§çä¾åæ¯ç¼åãæä»¬å¯ä»¥åå¨ï¼âç¼åâï¼å½æ°çç»æï¼ä»¥ä¾¿å°æ¥å¯¹åä¸ä¸ªå¯¹è±¡çè°ç¨å¯ä»¥éç¨è¿ä¸ªç»æã
为äºå®ç°è¿ä¸ç¹ï¼æä»¬å¯ä»¥ä½¿ç¨ Mapï¼éæä½³æ¹æ¡ï¼ï¼
// ð cache.js
let cache = new Map();
// 计ç®å¹¶è®°ä½ç»æ
function process(obj) {
if (!cache.has(obj)) {
let result = /* calculations of the result for */ 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ï¼åï¼è¯¥å¯¹è±¡ä¾ç¶å¨ cache ä¸ï¼å¹¶å æ®çå
åï¼ï¼
对äºå¤æ¬¡è°ç¨åä¸ä¸ªå¯¹è±¡ï¼å®åªéå¨ç¬¬ä¸æ¬¡è°ç¨æ¶è®¡ç®åºç»æï¼ä¹åçè°ç¨å¯ä»¥ç´æ¥ä» cache ä¸è·åãè¿æ ·åçç¼ºç¹æ¯ï¼å½æä»¬ä¸åéè¦è¿ä¸ªå¯¹è±¡çæ¶åéè¦æ¸
ç cacheã
妿æä»¬ç¨ WeakMap æ¿ä»£ Mapï¼ä¾¿ä¸ä¼åå¨è¿ä¸ªé®é¢ãå½å¯¹è±¡è¢«åå¾åæ¶æ¶ï¼å¯¹åºç¼åçç»æä¹ä¼è¢«èªå¨ä»å
å䏿¸
é¤ã
// ð cache.js
let cache = new WeakMap();
// 计ç®å¹¶è®°ç»æ
function process(obj) {
if (!cache.has(obj)) {
let result = /* calculate the result for */ 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;
// æ æ³è·å cache.sizeï¼å ä¸ºå®æ¯ä¸ä¸ª WeakMapï¼
// è¦ä¹æ¯ 0ï¼æå³å°å为 0
// å½ obj 被åå¾åæ¶ï¼ç¼åçæ°æ®ä¹ä¼è¢«æ¸
é¤
WeakSet
WeakSet ç表ç°ç±»ä¼¼ï¼
- ä¸
Set类似ï¼ä½æ¯æä»¬åªè½åWeakSetæ·»å 对象ï¼èä¸è½æ¯åå§å¼ï¼ã - å¯¹è±¡åªæå¨å
¶å®æä¸ªï¼äºï¼å°æ¹è½è¢«è®¿é®çæ¶åï¼æè½çå¨
WeakSetä¸ã - è·
Set䏿 ·ï¼WeakSetæ¯æaddï¼hasådeleteæ¹æ³ï¼ä½ä¸æ¯æsizeåkeys()ï¼å¹¶ä¸ä¸å¯è¿ä»£ã
åâå¼±ï¼weakï¼âçåæ¶ï¼å®ä¹å¯ä»¥ä½ä¸ºé¢å¤çåå¨ç©ºé´ãä½å¹¶ééå¯¹ä»»ææ°æ®ï¼èæ¯éå¯¹âæ¯/å¦âçäºå®ã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 ç°å¨æä¸¤ä¸ªç¨æ·äº
// æ£æ¥ John æ¯å¦æ¥è®¿è¿ï¼
alert(visitedSet.has(john)); // true
// æ£æ¥ Mary æ¯å¦æ¥è®¿è¿ï¼
alert(visitedSet.has(mary)); // false
john = null;
// visitedSet å°è¢«èªå¨æ¸
ç(å³èªå¨æ¸
é¤å
¶ä¸å·²å¤±æçå¼ john)
WeakMap å WeakSet æææ¾çå±éæ§å°±æ¯ä¸è½è¿ä»£ï¼å¹¶ä¸æ æ³è·åææå½åå
容ã飿 ·å¯è½ä¼é æä¸ä¾¿ï¼ä½æ¯å¹¶ä¸ä¼é»æ¢ WeakMap/WeakSet 宿å
¶ä¸»è¦å·¥ä½ ââ 为å¨å
¶å®å°æ¹åå¨/管ççå¯¹è±¡æ°æ®æä¾âé¢å¤âåå¨ã
æ»ç»
WeakMap æ¯ç±»ä¼¼äº Map çéåï¼å®ä»
å
许对象ä½ä¸ºé®ï¼å¹¶ä¸ä¸æ¦éè¿å
¶ä»æ¹å¼æ æ³è®¿é®è¿äºå¯¹è±¡ï¼åå¾åæ¶ä¾¿ä¼å°è¿äºå¯¹è±¡ä¸å
¶å
³èå¼ä¸åå é¤ã
WeakSet æ¯ç±»ä¼¼äº Set çéåï¼å®ä»
åå¨å¯¹è±¡ï¼å¹¶ä¸ä¸æ¦éè¿å
¶ä»æ¹å¼æ æ³è®¿é®è¿äºå¯¹è±¡ï¼åå¾åæ¶ä¾¿ä¼å°è¿äºå¯¹è±¡å é¤ã
å®ä»¬ç主è¦ä¼ç¹æ¯å®ä»¬å¯¹å¯¹è±¡æ¯å¼±å¼ç¨ï¼æä»¥è¢«å®ä»¬å¼ç¨ç对象å¾å®¹æå°è¢«å徿¶éå¨ç§»é¤ã
è¿æ¯ä»¥ä¸æ¯æ clearãsizeãkeysãvalues çä½ä¸ºä»£ä»·æ¢æ¥çâ¦â¦
WeakMap å WeakSet 被ç¨ä½â主è¦â对象åå¨ä¹å¤çâè¾
å©âæ°æ®ç»æã䏿¦å°å¯¹è±¡ä»ä¸»åå¨å¨ä¸å é¤ï¼å¦æè¯¥å¯¹è±¡ä»
被ç¨ä½ WeakMap æ WeakSet çé®ï¼é£ä¹è¯¥å¯¹è±¡å°è¢«èªå¨æ¸
é¤ã
è¯è®º
<code>æ ç¾æå ¥åªæå 个è¯ç代ç ï¼æå ¥å¤è¡ä»£ç å¯ä»¥ä½¿ç¨<pre>æ ç¾ï¼å¯¹äºè¶ è¿ 10 è¡ç代ç ï¼å»ºè®®ä½ ä½¿ç¨æ²ç®±ï¼plnkrï¼JSBinï¼codepenâ¦ï¼