国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

ES6 系列之 WeakMap的使用示例

2019-11-19 13:20:18
字體:
來源:轉載
供稿:網友

前言

我們先從 WeakMap 的特性說起,然后聊聊 WeakMap 的一些應用場景。

特性

1. WeakMap 只接受對象作為鍵名

const map = new WeakMap();map.set(1, 2);// TypeError: Invalid value used as weak map keymap.set(null, 2);// TypeError: Invalid value used as weak map key

2. WeakMap 的鍵名所引用的對象是弱引用

這句話其實讓我非常費解,我個人覺得這句話真正想表達的意思應該是:

WeakMaps hold "weak" references to key objects,

翻譯過來應該是 WeakMaps 保持了對鍵名所引用的對象的弱引用。

我們先聊聊弱引用:

在計算機程序設計中,弱引用與強引用相對,是指不能確保其引用的對象不會被垃圾回收器回收的引用。 一個對象若只被弱引用所引用,則被認為是不可訪問(或弱可訪問)的,并因此可能在任何時刻被回收。

在 JavaScript 中,一般我們創建一個對象,都是建立一個強引用:

var obj = new Object();

只有當我們手動設置 obj = null 的時候,才有可能回收 obj 所引用的對象。

而如果我們能創建一個弱引用的對象:

// 假設可以這樣創建一個var obj = new WeakObject();

我們什么都不用做,只用靜靜的等待垃圾回收機制執行,obj 所引用的對象就會被回收。

我們再來看看這句:

WeakMaps 保持了對鍵名所引用的對象的弱引用

正常情況下,我們舉個例子:

const key = new Array(5 * 1024 * 1024);const arr = [ [key, 1]];

使用這種方式,我們其實建立了 arr 對 key 所引用的對象(我們假設這個真正的對象叫 Obj)的強引用。

所以當你設置 key = null 時,只是去掉了 key 對 Obj 的強引用,并沒有去除 arr 對 Obj 的強引用,所以 Obj 還是不會被回收掉。

Map 類型也是類似:

let map = new Map();let key = new Array(5 * 1024 * 1024);// 建立了 map 對 key 所引用對象的強引用map.set(key, 1);// key = null 不會導致 key 的原引用對象被回收key = null;

我們可以通過 Node 來證明一下這個問題:

// 允許手動執行垃圾回收機制node --expose-gcglobal.gc();// 返回 Nodejs 的內存占用情況,單位是 bytesprocess.memoryUsage(); // heapUsed: 4640360 ≈ 4.4Mlet map = new Map();let key = new Array(5 * 1024 * 1024);map.set(key, 1);global.gc();process.memoryUsage(); // heapUsed: 46751472 注意這里大約是 44.6Mkey = null;global.gc();process.memoryUsage(); // heapUsed: 46754648 ≈ 44.6M// 這句話其實是無用的,因為 key 已經是 null 了map.delete(key);global.gc();process.memoryUsage(); // heapUsed: 46755856 ≈ 44.6M

如果你想要讓 Obj 被回收掉,你需要先 delete(key) 然后再 key = null:

let map = new Map();let key = new Array(5 * 1024 * 1024);map.set(key, 1);map.delete(key);key = null;

我們依然通過 Node 證明一下:

node --expose-gcglobal.gc();process.memoryUsage(); // heapUsed: 4638376 ≈ 4.4Mlet map = new Map();let key = new Array(5 * 1024 * 1024);map.set(key, 1);global.gc();process.memoryUsage(); // heapUsed: 46727816 ≈ 44.6Mmap.delete(key);global.gc();process.memoryUsage(); // heapUsed: 46748352 ≈ 44.6Mkey = null;global.gc();process.memoryUsage(); // heapUsed: 4808064 ≈ 4.6M

這個時候就要說到 WeakMap 了:

const wm = new WeakMap();let key = new Array(5 * 1024 * 1024);wm.set(key, 1);key = null;

當我們設置 wm.set(key, 1) 時,其實建立了 wm 對 key 所引用的對象的弱引用,但因為 let key = new Array(5 * 1024 * 1024) 建立了 key 對所引用對象的強引用,被引用的對象并不會被回收,但是當我們設置 key = null 的時候,就只有 wm 對所引用對象的弱引用,下次垃圾回收機制執行的時候,該引用對象就會被回收掉。

我們用 Node 證明一下:

node --expose-gcglobal.gc();process.memoryUsage(); // heapUsed: 4638992 ≈ 4.4Mconst wm = new WeakMap();let key = new Array(5 * 1024 * 1024);wm.set(key, 1);global.gc();process.memoryUsage(); // heapUsed: 46776176 ≈ 44.6Mkey = null;global.gc();process.memoryUsage(); // heapUsed: 4800792 ≈ 4.6M

所以 WeakMap 可以幫你省掉手動刪除對象關聯數據的步驟,所以當你不能或者不想控制關聯數據的生命周期時就可以考慮使用 WeakMap。

總結這個弱引用的特性,就是 WeakMaps 保持了對鍵名所引用的對象的弱引用,即垃圾回收機制不將該引用考慮在內。只要所引用的對象的其他引用都被清除,垃圾回收機制就會釋放該對象所占用的內存。也就是說,一旦不再需要,WeakMap 里面的鍵名對象和所對應的鍵值對會自動消失,不用手動刪除引用。

也正是因為這樣的特性,WeakMap 內部有多少個成員,取決于垃圾回收機制有沒有運行,運行前后很可能成員個數是不一樣的,而垃圾回收機制何時運行是不可預測的,因此 ES6 規定 WeakMap 不可遍歷。

所以 WeakMap 不像 Map,一是沒有遍歷操作(即沒有keys()、values()和entries()方法),也沒有 size 屬性,也不支持 clear 方法,所以 WeakMap只有四個方法可用:get()、set()、has()、delete()。

應用

1. 在 DOM 對象上保存相關數據

傳統使用 jQuery 的時候,我們會通過 $.data() 方法在 DOM 對象上儲存相關信息(就比如在刪除按鈕元素上儲存帖子的 ID 信息),jQuery 內部會使用一個對象管理 DOM 和對應的數據,當你將 DOM 元素刪除,DOM 對象置為空的時候,相關聯的數據并不會被刪除,你必須手動執行 $.removeData() 方法才能刪除掉相關聯的數據,WeakMap 就可以簡化這一操作:

let wm = new WeakMap(), element = document.querySelector(".element");wm.set(element, "data");let value = wm.get(elemet);console.log(value); // dataelement.parentNode.removeChild(element);element = null;

2. 數據緩存

從上一個例子,我們也可以看出,當我們需要關聯對象和數據,比如在不修改原有對象的情況下儲存某些屬性或者根據對象儲存一些計算的值等,而又不想管理這些數據的死活時非常適合考慮使用 WeakMap。數據緩存就是一個非常好的例子:

const cache = new WeakMap();function countOwnKeys(obj) {  if (cache.has(obj)) {    console.log('Cached');    return cache.get(obj);  } else {    console.log('Computed');    const count = Object.keys(obj).length;    cache.set(obj, count);    return count;  }}

3. 私有屬性

WeakMap 也可以被用于實現私有變量,不過在 ES6 中實現私有變量的方式有很多種,這只是其中一種:

const privateData = new WeakMap();class Person {  constructor(name, age) {    privateData.set(this, { name: name, age: age });  }  getName() {    return privateData.get(this).name;  }  getAge() {    return privateData.get(this).age;  }}export default Person;

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 库车县| 读书| 阿鲁科尔沁旗| 达拉特旗| 进贤县| 遂昌县| 甘肃省| 吴川市| 富蕴县| 右玉县| 静安区| 上犹县| 太仆寺旗| 台北市| 赞皇县| 无极县| 永泰县| 和静县| 六安市| 哈密市| 远安县| 手游| 武定县| 宿松县| 咸阳市| 鹿泉市| 马边| 通辽市| 天台县| 常州市| 正宁县| 武山县| 桃园市| 察哈| 定陶县| 岳普湖县| 辽中县| 呼玛县| 邹平县| 五华县| 韶关市|