JavaScript?WeakMap的具體使用
前言
我在處理一個復雜對象的深拷貝方法時接觸到WeakMap, 其作為緩存結構以解決對象內(nèi)部的循環(huán)引用問題. 為了改造這個方法, 決定研究WeakMap.
一、為何選用WeakMap
WeakMap和Map都可以使用對象作為鍵, Map也可以使用基本數(shù)據(jù)類型作為鍵, 在特殊的情況下(都使用對象作為鍵), 兩者看起來并無差別.
1. Map
Map會阻止JavaScript的內(nèi)存回收機制對 以一個已經(jīng)被回收的對象作為鍵的元素 進行回收.
與Map內(nèi)存儲元素的方式有關:
A map API could be implemented in JavaScript with two arrays (one for keys, one for values) shared by the four API methods.
`map`在JavaScript內(nèi)可通過使兩個數(shù)組被4種方法共享來實現(xiàn), 向`Map`內(nèi)設置元素時分別將鍵和值`push`進這兩個數(shù)組.
Setting elements on this map would involve pushing a key and value onto the end of each of those arrays simultaneously.
訪問`Map`取值時需要遍歷, 從兩個數(shù)組內(nèi)找到匹配的值.
var sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', 'meow');
sayings.set('elephant', 'toot');
sayings.size; // 3
sayings.get('fox'); // undefined
sayings.has('bird'); // false
sayings.delete('dog');
sayings.has('dog'); // false
for (var [key, value] of sayings) {
? console.log(key + ' goes ' + value);
}
// "cat goes meow"
// "elephant goes toot"
sayings.clear();
sayings.size; // 0首先Map內(nèi)部基于數(shù)組實現(xiàn), 取值賦值需要遍歷, 時間復雜度上來了:
The first one is an O(n) set and search (n being the number of keys in the map)
首先設置和查找的時間復雜度都是O(n), n是Map內(nèi)鍵的數(shù)量.
since both operations must iterate through the list of keys to find a matching value.
因為兩個操作都必須遍歷每一個鍵以找到匹配的值.
其次數(shù)組會一直保留著對元素的引用, 這跟元素是否為引用類型無關, 只要數(shù)組不被銷毀, 元素的引用也不會被銷毀:
let ele1 = 'ele1';
let ele2 = { key: 'value' };
let arr = [ ele1, ele2 ];
ele1 = null; // 設置為null脫離當前執(zhí)行環(huán)境, 以便回收機制回收
ele2.key = null;
console.log(arr);
// [ 'ele1', { key: 'null' } ]前面提到Map內(nèi)部可以通過兩個數(shù)組實現(xiàn), 那么意味著在Map需要銷毀前, Map內(nèi)的鍵和值都無法被JavaScript垃圾回收機制回收, Map可能會變得臃腫龐大導致內(nèi)存不足(內(nèi)存泄漏).
持有原始對象引用的映射實際上意味著對象不能被垃圾回收, 這可能會導致意外的內(nèi)存問題.
如果你希望存儲在映射中的對象具有與原始對象相同的生命周期, 請考慮使用 WeakMap.
2. WeakMap
WeakMap同Map是鍵值對的集合, 但它的鍵被弱保持, 即當鍵所指的對象未在其他地方被引用時, 將被垃圾回收機制回收.
其鍵必須是對象, 值可以是任意數(shù)據(jù)類型.
也由于這種弱引用實現(xiàn)的垃圾回收可執(zhí)行, WeakMap內(nèi)元素的存在變得不可預知(可能垃圾回收機制目前沒有回收至此處, 但此處應當回收.), 為了防止執(zhí)行時出現(xiàn)意外, WeakMap沒有提供枚舉方法.
正由于這樣的弱引用, WeakMap的key是不可枚舉的(沒有方法能給出所有的 key).
如果key可枚舉, 其列表將受垃圾回收機制的影響, 從而得到不確定的結果。
但是WeakMap提供的接口與Map相同, 可以通過接口穩(wěn)定的訪問元素.
let ele1 = { key: "value" };
let weak = new WeakMap();
weak.set(ele1, "ele1");
ele1 = null;
console.log(weak); // WeakMap { <items unknown> } 不賦值null此處結果相同
console.log(weak.get(ele1)); // undefined 銷毀 不賦值null此處為'ele1'總之, 相比Map, 它更干凈利落, 更節(jié)約內(nèi)存.
但是你如果有枚舉需求, 或者就是需要一直保存著key不回收, 那就用Map.
二、WeakMap原型方法
指明需要何種操作, 并指明需要操作的鍵值對的key, 直接傳變量即可.
| 方法 | 描述 |
|---|---|
WeakMap.prototype.delete(key) | 刪除WeakMap中與key相匹配的value. |
WeakMap.prototype.get(key) | 返回WeakMap中與key相關聯(lián)的值, 如果key不存在則返回undefined. |
WeakMap.prototype.has(key) | 返回布爾值, 斷言WeakMap對象中該key是否存在. |
WeakMap.prototype.set(key, value) | 向WeakMap中設置一組新的鍵值對, 返回設置完畢后的WeakMap對象. |
總結
到此這篇關于JavaScript WeakMap的具體使用的文章就介紹到這了,更多相關JavaScript WeakMap內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript實現(xiàn)單擊網(wǎng)頁任意位置打開新窗口與關閉窗口的方法
這篇文章主要介紹了JavaScript實現(xiàn)單擊網(wǎng)頁任意位置打開新窗口與關閉窗口的方法,涉及javascript窗口的相關操作函數(shù)與使用技巧,需要的朋友可以參考下2017-09-09
JS來動態(tài)的修改url實現(xiàn)對url的增刪查改
通過get方式提交post表單等方式來動態(tài)修改url存在諸多的不妥,因此,想到了通過JS來動態(tài)的修改url,來實現(xiàn)對url的增刪查改2014-09-09

