第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開(kāi)發(fā)者教程

ES6-10 入門(mén)教程

ES6+ WeakMap

1. 前言

前面我們已經(jīng)學(xué)了 Set 和對(duì)應(yīng)的 WeakSet,Map 對(duì)應(yīng)也有 WeakMap,在學(xué)習(xí) WeakSet 時(shí)我們已經(jīng)接觸到弱引的相關(guān)知識(shí),本節(jié)我們將結(jié)合 WeakMap 深入的理解弱引用的相關(guān)問(wèn)題。

由前面學(xué)到的 Set 和 WeakSet 具有很多相似的地方,比如它們存放的都是獨(dú)一無(wú)二的元素。所以,對(duì) Map 和 WeakMap 也可以進(jìn)行類(lèi)比,WeakMap 中也存放的是鍵值對(duì)。不同的是 WeakMap 的 key 只能是對(duì)象,值可以是任意類(lèi)型的,和 WeakSet 一樣 WeakMap 對(duì) key 的引用是弱引用。

2. WeakMap 基本用法

WeakMap 像 Map 一樣可以接受一個(gè)二維數(shù)組進(jìn)行初始化。

var wm = new WeakMap([
  [{name: 'imooc'}, 'imooc'],
  [{name: 'lesson'}, 'ES6 Wiki']
])
console.log(wm)

上面的代碼打印結(jié)果如下:

圖片描述

從打印的結(jié)果可以大概了解 WeakMap 的存儲(chǔ)方式,WeakMap 的實(shí)例本來(lái)就是一個(gè)對(duì)象。

WeakMap 只提供了四個(gè)方法用于操作數(shù)據(jù)。

方法名 描述
set 接收鍵值對(duì),向 WeakMap 實(shí)例中添加元素
get 傳入指定的 key 獲取 WeakMap 實(shí)例上的值
has 傳入指定的 key 查找在 WeakMap 實(shí)例中是否存在
delete 傳入指定的 key 刪除 WeakMap 實(shí)例中對(duì)應(yīng)的值

看如下實(shí)例:

var wm1 = new WeakMap();
var wm2 = new WeakMap();
var wm3 = new WeakMap();

var o1 = {name: 'imooc'};
var o2 = function(){};
var o3 = window;

// 使用 set 方法添加元素,value 可以是任意值,包括對(duì)象、函數(shù)甚至另外一個(gè)WeakMap對(duì)象
wm1.set(o1, 'ES6 Wiki');
wm1.set(o2, 10);
wm2.set(o1, o2);
wm2.set(o3, null);
wm2.set(wm1, wm2);

wm1.get(o2); // 10
wm2.get(o2); // undefined,wm2 中沒(méi)有 o2 這個(gè)鍵
wm2.get(o3); // null

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (即使值是null)

wm3.set(o1, 'lesson is ES6 Wiki!');
wm3.get(o1); // lesson is ES6 Wiki!

wm1.has(o1);   // true
wm1.delete(o1);
wm1.has(o1);   // false

上面的實(shí)例基本涵蓋了 WeakMap 四種方法的基本使用情況,上面也提到了 WeakMap 的 key 只能是對(duì)象類(lèi)型的,如果 WeakMap 的 key 是基本類(lèi)型數(shù)據(jù)時(shí)就會(huì)報(bào)錯(cuò)。

var wm = new WeakMap();
wm.set('lesson', 'ES6 Wiki');
// Uncaught TypeError: Invalid錯(cuò)誤value used as weak map key

上面代碼中在設(shè)置 wm 值時(shí),報(bào)錯(cuò)了。從報(bào)錯(cuò)類(lèi)型知道是一個(gè)類(lèi)型錯(cuò)誤,弱引用映射的鍵是無(wú)效的。

3. WeakMap 使用場(chǎng)景

上節(jié)我們學(xué)習(xí)了 Map 的使用,在 JavaScript 中對(duì)對(duì)象的引用都是強(qiáng)保留的,這意味著只要持有該對(duì)象的引用,垃圾回收機(jī)制就不會(huì)回收該對(duì)象。

var obj = {a: 10, b: 88};

上面是一個(gè)字面量對(duì)象,只要我們?cè)L問(wèn) obj 對(duì)象,或者任何地方有引用該對(duì)象,這個(gè)對(duì)象就不會(huì)被垃圾回收。而在 ES6 之前 JavaScript 中沒(méi)有弱引用概念,弱引用的本質(zhì)上就是不會(huì)影響垃圾回收機(jī)制。其實(shí),WeakMap 并不是真正意義上的弱引用,只要鍵仍然存在,它就強(qiáng)引用其上的內(nèi)容。WeakMap 僅在鍵被垃圾回收之后,才弱引用它的內(nèi)容,所以也不用太糾結(jié)其中的弱。

在官方上對(duì)為什么使用 WeakMap 做了描述,Map 在存儲(chǔ)值是有順序的,這種順序是通過(guò)二維數(shù)組的形式來(lái)完成的。我們知道 Map 在初始化時(shí)接受一個(gè)數(shù)組,數(shù)組中的每一項(xiàng)也是一個(gè)數(shù)組,這個(gè)數(shù)組中包含兩個(gè)值,一個(gè)存放的是鍵,一個(gè)存放的是值。新添加的值會(huì)添加到數(shù)組的末尾,從而使得鍵值具有索引的含義。在取值時(shí)就需要進(jìn)行遍歷,通過(guò)索引取出對(duì)應(yīng)的值。

但是這樣存在兩個(gè)很大的缺陷:

  1. 賦值和搜索的時(shí)間復(fù)雜度都是 O (n) (n 是鍵值對(duì)的個(gè)數(shù)),因?yàn)檫@兩個(gè)操作都是要遍歷整個(gè)數(shù)組才能完成的;
  2. 可能會(huì)導(dǎo)致內(nèi)存泄漏,因?yàn)閿?shù)組會(huì)一直引用每個(gè)鍵和值。這種引用使得垃圾回收算法不能回收處理它們,即使沒(méi)有任何引用存在。

相比之下,原生的 WeakMap 持有的是 “弱引用”,這意味著它不會(huì)影響垃圾回收。WeakMap 中的 key 只有在鍵值存在的情況才會(huì)引用,而且只是一個(gè)讀取操作,并不會(huì)對(duì)引用的值產(chǎn)生影響。也正因?yàn)檫@樣的弱引用關(guān)系,導(dǎo)致 WeakMap 中的 key 是不可枚舉的,假設(shè) key 是可枚舉的,就會(huì)對(duì)該值產(chǎn)生引用關(guān)系,影響垃圾回收。

如果只是單純地向?qū)ο笊咸砑又涤糜跈z查某些邏輯判斷,又不想影響垃圾回收機(jī)制,這個(gè)時(shí)候就可以使用 WeakMap。這里說(shuō)一點(diǎn),在一些框架中已經(jīng)使用了像 WeakMap 和 WeakSet 這樣的數(shù)據(jù)結(jié)構(gòu),其中 Vue3 就引入了這樣的新數(shù)據(jù)進(jìn)行一些必要的邏輯判斷,有興趣的可以去扒扒 Vue3 的源碼研究研究。

4. 總結(jié)

本節(jié)主要介紹了 WeakMap 的使用和應(yīng)用場(chǎng)景,這里要說(shuō)明的一點(diǎn)是:WeakMap 不算真正意義上的弱引用方式,只要鍵仍然存在,它就強(qiáng)引用其上的內(nèi)容。最新的 ES 方案提出了 WeakRef 的 API 作為真正的弱引用方式,現(xiàn)在還處于不穩(wěn)定期間,也還存在一些問(wèn)題,如果有興趣的可以研究一下。最后,在 WeakMap 的使用上,大多數(shù)都是用來(lái)進(jìn)行一些必要的邏輯判斷的。在 WeakMap 實(shí)例上添加一個(gè)對(duì)已知對(duì)象的引用,從而在需要使用時(shí),對(duì)該對(duì)象進(jìn)行必要的邏輯判斷。