成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

ES6 系列之 WeakMap

CollinPeng / 3221人閱讀

摘要:一個(gè)對(duì)象若只被弱引用所引用,則被認(rèn)為是不可訪問或弱可訪問的,并因此可能在任何時(shí)刻被回收。也就是說,一旦不再需要,里面的鍵名對(duì)象和所對(duì)應(yīng)的鍵值對(duì)會(huì)自動(dòng)消失,不用手動(dòng)刪除引用。如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤?,?qǐng)務(wù)必給予指正,十分感謝。

前言

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

特性 1. WeakMap 只接受對(duì)象作為鍵名
const map = new WeakMap();
map.set(1, 2);
// TypeError: Invalid value used as weak map key
map.set(null, 2);
// TypeError: Invalid value used as weak map key
2. WeakMap 的鍵名所引用的對(duì)象是弱引用

這句話其實(shí)讓我非常費(fèi)解,我個(gè)人覺得這句話真正想表達(dá)的意思應(yīng)該是:

WeakMaps hold "weak" references to key objects,

翻譯過來應(yīng)該是 WeakMaps 保持了對(duì)鍵名所引用的對(duì)象的弱引用。

我們先聊聊弱引用:

在計(jì)算機(jī)程序設(shè)計(jì)中,弱引用與強(qiáng)引用相對(duì),是指不能確保其引用的對(duì)象不會(huì)被垃圾回收器回收的引用。 一個(gè)對(duì)象若只被弱引用所引用,則被認(rèn)為是不可訪問(或弱可訪問)的,并因此可能在任何時(shí)刻被回收。

在 JavaScript 中,一般我們創(chuàng)建一個(gè)對(duì)象,都是建立一個(gè)強(qiáng)引用:

var obj = new Object();

只有當(dāng)我們手動(dòng)設(shè)置 obj = null 的時(shí)候,才有可能回收 obj 所引用的對(duì)象。

而如果我們能創(chuàng)建一個(gè)弱引用的對(duì)象:

// 假設(shè)可以這樣創(chuàng)建一個(gè)
var obj = new WeakObject();

我們什么都不用做,只用靜靜的等待垃圾回收機(jī)制執(zhí)行,obj 所引用的對(duì)象就會(huì)被回收。

我們?cè)賮砜纯催@句:

WeakMaps 保持了對(duì)鍵名所引用的對(duì)象的弱引用

正常情況下,我們舉個(gè)例子:

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

使用這種方式,我們其實(shí)建立了 arr 對(duì) key 所引用的對(duì)象(我們假設(shè)這個(gè)真正的對(duì)象叫 Obj)的強(qiáng)引用。

所以當(dāng)你設(shè)置 key = null 時(shí),只是去掉了 key 對(duì) Obj 的強(qiáng)引用,并沒有去除 arr 對(duì) Obj 的強(qiáng)引用,所以 Obj 還是不會(huì)被回收掉。

Map 類型也是類似:

let map = new Map();
let key = new Array(5 * 1024 * 1024);

// 建立了 map 對(duì) key 所引用對(duì)象的強(qiáng)引用
map.set(key, 1);
// key = null 不會(huì)導(dǎo)致 key 的原引用對(duì)象被回收
key = null;

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

// 允許手動(dòng)執(zhí)行垃圾回收機(jī)制
node --expose-gc

global.gc();
// 返回 Nodejs 的內(nèi)存占用情況,單位是 bytes
process.memoryUsage(); // heapUsed: 4640360 ≈ 4.4M

let map = new Map();
let key = new Array(5 * 1024 * 1024);
map.set(key, 1);
global.gc();
process.memoryUsage(); // heapUsed: 46751472 注意這里大約是 44.6M

key = null;
global.gc();
process.memoryUsage(); // heapUsed: 46754648 ≈ 44.6M

// 這句話其實(shí)是無用的,因?yàn)?key 已經(jīng)是 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-gc

global.gc();
process.memoryUsage(); // heapUsed: 4638376 ≈ 4.4M

let map = new Map();
let key = new Array(5 * 1024 * 1024);
map.set(key, 1);
global.gc();
process.memoryUsage(); // heapUsed: 46727816 ≈ 44.6M

map.delete(key);
global.gc();
process.memoryUsage(); // heapUsed: 46748352 ≈ 44.6M

key = null;
global.gc();
process.memoryUsage(); // heapUsed: 4808064 ≈ 4.6M

這個(gè)時(shí)候就要說到 WeakMap 了:

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

當(dāng)我們?cè)O(shè)置 wm.set(key, 1) 時(shí),其實(shí)建立了 wm 對(duì) key 所引用的對(duì)象的弱引用,但因?yàn)?let key = new Array(5 * 1024 * 1024) 建立了 key 對(duì)所引用對(duì)象的強(qiáng)引用,被引用的對(duì)象并不會(huì)被回收,但是當(dāng)我們?cè)O(shè)置 key = null 的時(shí)候,就只有 wm 對(duì)所引用對(duì)象的弱引用,下次垃圾回收機(jī)制執(zhí)行的時(shí)候,該引用對(duì)象就會(huì)被回收掉。

我們用 Node 證明一下:

node --expose-gc

global.gc();
process.memoryUsage(); // heapUsed: 4638992 ≈ 4.4M

const wm = new WeakMap();
let key = new Array(5 * 1024 * 1024);
wm.set(key, 1);
global.gc();
process.memoryUsage(); // heapUsed: 46776176 ≈ 44.6M

key = null;
global.gc();
process.memoryUsage(); // heapUsed: 4800792 ≈ 4.6M

所以 WeakMap 可以幫你省掉手動(dòng)刪除對(duì)象關(guān)聯(lián)數(shù)據(jù)的步驟,所以當(dāng)你不能或者不想控制關(guān)聯(lián)數(shù)據(jù)的生命周期時(shí)就可以考慮使用 WeakMap。

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

也正是因?yàn)檫@樣的特性,WeakMap 內(nèi)部有多少個(gè)成員,取決于垃圾回收機(jī)制有沒有運(yùn)行,運(yùn)行前后很可能成員個(gè)數(shù)是不一樣的,而垃圾回收機(jī)制何時(shí)運(yùn)行是不可預(yù)測(cè)的,因此 ES6 規(guī)定 WeakMap 不可遍歷。

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

應(yīng)用 1. 在 DOM 對(duì)象上保存相關(guān)數(shù)據(jù)

傳統(tǒng)使用 jQuery 的時(shí)候,我們會(huì)通過 $.data() 方法在 DOM 對(duì)象上儲(chǔ)存相關(guān)信息(就比如在刪除按鈕元素上儲(chǔ)存帖子的 ID 信息),jQuery 內(nèi)部會(huì)使用一個(gè)對(duì)象管理 DOM 和對(duì)應(yīng)的數(shù)據(jù),當(dāng)你將 DOM 元素刪除,DOM 對(duì)象置為空的時(shí)候,相關(guān)聯(lián)的數(shù)據(jù)并不會(huì)被刪除,你必須手動(dòng)執(zhí)行 $.removeData() 方法才能刪除掉相關(guān)聯(lián)的數(shù)據(jù),WeakMap 就可以簡化這一操作:

let wm = new WeakMap(), element = document.querySelector(".element");
wm.set(element, "data");

let value = wm.get(elemet);
console.log(value); // data

element.parentNode.removeChild(element);
element = null;
2. 數(shù)據(jù)緩存

從上一個(gè)例子,我們也可以看出,當(dāng)我們需要關(guān)聯(lián)對(duì)象和數(shù)據(jù),比如在不修改原有對(duì)象的情況下儲(chǔ)存某些屬性或者根據(jù)對(duì)象儲(chǔ)存一些計(jì)算的值等,而又不想管理這些數(shù)據(jù)的死活時(shí)非常適合考慮使用 WeakMap。數(shù)據(jù)緩存就是一個(gè)非常好的例子:

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 也可以被用于實(shí)現(xiàn)私有變量,不過在 ES6 中實(shí)現(xiàn)私有變量的方式有很多種,這只是其中一種:

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;
ES6 系列

ES6 系列目錄地址:https://github.com/mqyqingfeng/Blog

ES6 系列預(yù)計(jì)寫二十篇左右,旨在加深 ES6 部分知識(shí)點(diǎn)的理解,重點(diǎn)講解塊級(jí)作用域、標(biāo)簽?zāi)0?、箭頭函數(shù)、Symbol、Set、Map 以及 Promise 的模擬實(shí)現(xiàn)、模塊加載方案、異步處理等內(nèi)容。

如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑?qǐng)務(wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎 star,對(duì)作者也是一種鼓勵(lì)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96299.html

相關(guān)文章

  • ES6 系列私有變量的實(shí)現(xiàn)

    摘要:前言在閱讀入門的時(shí)候,零散的看到有私有變量的實(shí)現(xiàn),所以在此總結(jié)一篇。構(gòu)造函數(shù)應(yīng)該只做對(duì)象初始化的事情,現(xiàn)在為了實(shí)現(xiàn)私有變量,必須包含部分方法的實(shí)現(xiàn),代碼組織上略不清晰。 前言 在閱讀 《ECMAScript 6 入門》的時(shí)候,零散的看到有私有變量的實(shí)現(xiàn),所以在此總結(jié)一篇。 1. 約定 實(shí)現(xiàn) class Example { constructor() { this...

    lentoo 評(píng)論0 收藏0
  • ES6腳丫系列】Set+WeakSet+Map+WeakMap

    摘要:返回一個(gè)布爾值,表示該值是否為的成員。清除所有成員,沒有返回值。返回的都是遍歷器對(duì)象。結(jié)構(gòu)的實(shí)例的方法,用于對(duì)每個(gè)成員執(zhí)行某種操作,沒有返回值。這個(gè)特點(diǎn)意味著,無法引用的成員,因此是不可遍歷的。數(shù)組成員是一個(gè)或多個(gè)表示鍵值對(duì)的一維數(shù)組。 本文字?jǐn)?shù):4700+,閱讀時(shí)間約10分鐘。 如果有理解不到位的地方,歡迎大家糾錯(cuò)。 一、Set 【01】Set是一種數(shù)據(jù)結(jié)構(gòu)。類似于數(shù)組,但是成員的值...

    lyning 評(píng)論0 收藏0
  • es6 Map和WeakMap

    摘要:事實(shí)上,不僅僅是數(shù)組,任何具有接口且每個(gè)成員都是一個(gè)雙元素的數(shù)組的數(shù)據(jù)結(jié)構(gòu)都可以當(dāng)做構(gòu)造函數(shù)的參數(shù)。返回所有成員的遍歷器需要特別注意的是,的遍歷順序就是插入順序。轉(zhuǎn)為轉(zhuǎn)為,正常情況下,所有鍵名都是字符串。 Map JavaScript 的對(duì)象(Object),本質(zhì)上是鍵值對(duì)的集合(Hash 結(jié)構(gòu)),但是傳統(tǒng)上只能用字符串當(dāng)作鍵。這給它的使用帶來了很大的限制。為了解決這個(gè)問題,ES6 提...

    sPeng 評(píng)論0 收藏0
  • 【進(jìn)階4-3期】面試題如何實(shí)現(xiàn)一個(gè)深拷貝

    摘要:今天這篇文章我們來看看一道必會(huì)面試題,即如何實(shí)現(xiàn)一個(gè)深拷貝。木易楊注意這里使用上面測(cè)試用例測(cè)試一下一個(gè)簡單的深拷貝就完成了,但是這個(gè)實(shí)現(xiàn)還存在很多問題。 引言 上篇文章詳細(xì)介紹了淺拷貝 Object.assign,并對(duì)其進(jìn)行了模擬實(shí)現(xiàn),在實(shí)現(xiàn)的過程中,介紹了很多基礎(chǔ)知識(shí)。今天這篇文章我們來看看一道必會(huì)面試題,即如何實(shí)現(xiàn)一個(gè)深拷貝。本文會(huì)詳細(xì)介紹對(duì)象、數(shù)組、循環(huán)引用、引用丟失、Symbo...

    longmon 評(píng)論0 收藏0
  • ES6 - WeakMap

    Set有對(duì)應(yīng)的WeakSet, Map也有WeakMap。這一篇,我們就來學(xué)習(xí)一下WeakMap有寫什么特性。先來看一下WeakMap的基本特性: 1: WeakMap是一種存儲(chǔ)多個(gè)鍵值對(duì)的無序列表 2: WeakMap的鍵必須是非null的對(duì)象類型 3: WeakMap的鍵對(duì)應(yīng)的值,可以是任意類型 接下來看一下WeakMap的接口方法:一:WeakMap的新建與初始化與Map相同的,WeakM...

    Youngdze 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

CollinPeng

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<