Map、WeakMap與Set、WeakSet

Map和Set都是ES6中間添加的數(shù)據(jù)類型,最近在寫LeetCode的時(shí)候就能用到Map結(jié)構(gòu),同時(shí)之前看別人手寫代碼的時(shí)候也出現(xiàn)了weakmap結(jié)構(gòu),用本文記錄下這4者之間的關(guān)系和區(qū)別

Map

Map 對(duì)象保存鍵值對(duì),并且能夠記住鍵的原始插入順序。任何值(對(duì)象或者原始值都可以作為一個(gè)鍵或一個(gè)值。

和Object相比,Map也可以存儲(chǔ)鍵值對(duì)信息,但是Object只能存儲(chǔ)字符串/symbol-值的組合,Map則可以存儲(chǔ)值-值的信息,這個(gè)鍵值對(duì)的鍵名不限于字符串,各種類型的值(包括對(duì)象)都可以作為鍵名。

let data  = {}
let d = new Map()
let aa = [1,2,3]
data[aa] = 1
d.set([1,2,3],2)
console.log(data);
console.log(d);


Map結(jié)構(gòu)能夠很好的保存鍵的數(shù)據(jù)類型,而Object會(huì)將其轉(zhuǎn)成字符串保存,在對(duì)鍵值對(duì)有更多需求的時(shí)候用Map會(huì)更好。
下圖來(lái)自MDN

Map方法

添加刪除方法
set(key,value) 給Map對(duì)象設(shè)置key/value鍵值對(duì),返回這個(gè)Map對(duì)象(相對(duì)于JavaScript的Set,Set對(duì)象添加元素的方法叫add,而Map對(duì)象添加元素的方法為set)
get(key) 返回Map對(duì)象key相對(duì)的value值
delete(key) 刪除指定鍵
clear() 刪除所有的鍵值對(duì)
判斷方法
has(key) 判斷Map對(duì)象是否存在指定的key,如果不存在,則返回undefined。
遍歷方法
keys() 返回一個(gè)Iterator對(duì)象,按照插入的順序返回每一個(gè)key元素
values() 返回一個(gè)Iterator對(duì)象,按照插入的順序返回每一個(gè)value元素
entries() 返回一個(gè)Iterator對(duì)象,按照對(duì)象的插入順序返回[key,value]
forEach(callback,context) 按插入順序,循環(huán)執(zhí)行函數(shù)并把鍵值對(duì)作為參數(shù),context為執(zhí)行函數(shù)的上下文this

Map使用要點(diǎn)

Map可以接收數(shù)組傳參,并且作為鍵值對(duì)保存,傳參要點(diǎn)是```new Map([[參數(shù)1],[參數(shù)2]...]),此時(shí)Map接收的是一個(gè)二維數(shù)組。



另外任何具有Iterator接口,且每個(gè)成員都是一個(gè)雙元素的數(shù)組的數(shù)據(jù)結(jié)構(gòu)都可以當(dāng)做Map構(gòu)造函數(shù)的參數(shù)??梢杂胢ap和set互相來(lái)創(chuàng)建

var a = new Set([['aa',1],['bb',2]])
var b = new Map(a)
console.log(a);
console.log(b);
var c = new Map([['cc',1],['dd',2]])
var d = new Map(c)
console.log(c);
console.log(d);

Map中同一個(gè)鍵值對(duì)被設(shè)置多次,值會(huì)被最后一個(gè)覆蓋。

var c = new Map([['cc',1],['dd',2]])
c.set('11',1)
c.set('11',100)
console.log(c);
console.log(c.get('11'));

如果Map的鍵是一個(gè)原始數(shù)據(jù)類型,只要兩個(gè)鍵嚴(yán)格相同,就視為是同一個(gè)鍵,但是如果是引用類型,兩個(gè)引用值由于存儲(chǔ)地址不同,相同的會(huì)被視為兩個(gè)值。

var c = new Map()
var aa = [{'a':1}]
c.set(aa,1)
c.set([1,2,3],100)
console.log(c);
console.log(c.get([1,2,3]))
console.log(c.get([{'a':1}]))
console.log(c.get(aa))


[1,2,3][{'a':1}]因?yàn)槭且妙愋偷刂凡煌砸暈閮蓚€(gè)不同的值,這里也可以看出讀取一個(gè)未知的鍵,則返回undefined,但是如果用aa已經(jīng)訂好的參數(shù)就能拿到值。

WeakMap

WeakMap和Map的結(jié)構(gòu)一樣,但是他只接受引用類型的數(shù)據(jù)來(lái)作為鍵名。WeakMap的Weak個(gè)人理解是來(lái)自于他弱引用的特性。

WeakMaps 保持了對(duì)鍵名所引用的對(duì)象的弱引用
弱引用與強(qiáng)引用相對(duì),是指不能確保其引用的對(duì)象不會(huì)被垃圾回收器回收的引用。 一個(gè)對(duì)象若只被弱引用所引用,則被認(rèn)為是不可訪問(wèn)(或弱可訪問(wèn))的,并因此可能在任何時(shí)刻被回收。

可以這么理解當(dāng)需要往一個(gè)對(duì)象上添加點(diǎn)數(shù)據(jù),那就回對(duì)這個(gè)對(duì)象產(chǎn)生強(qiáng)引用,如果我們不手動(dòng)刪除引用,這個(gè)對(duì)象不會(huì)被垃圾回收機(jī)制回收。這里WeakMap的鍵名引用就是個(gè)弱引用,當(dāng)所引用的對(duì)象的其他引用都被清除,垃圾回收機(jī)制就會(huì)釋放該對(duì)象所占用的內(nèi)存。這里的WeakMap的鍵名引用就不會(huì)干擾垃圾回收機(jī)制。

所以根據(jù)上面這個(gè)規(guī)則,WeakMap是不能遍歷的,所以WeakMap不支持clear方法,不支持遍歷,也就沒(méi)有了keys、values、entries、forEach這4個(gè)方法,因?yàn)椴恢乐虚g的值在什么時(shí)候會(huì)被垃圾回收機(jī)制回收。
WeakMap只有set、get、has、delete方法,用法和用途都和Map一樣。

Set

Set平時(shí)常用與對(duì)數(shù)組去重的方法中,ES6定義的一種新的數(shù)據(jù)結(jié)構(gòu),在一個(gè)Set中可以存儲(chǔ)任何類型的唯一值,無(wú)論是原始值或者是對(duì)象引用。

let aa = [1,1,2,2,3,3,4,5,NaN,NaN,NaN,undefined,undefined,{},{}]
let s = new Set(aa)
console.log(aa)
console.log(s)


NaN和undefined都可以被存儲(chǔ)在Set 中,盡管NaN !== NaN但是這里會(huì)刪除,兩個(gè)相同的空對(duì)象是不同的元素,不會(huì)被去掉。

Set的方法

添加刪除
add(values):添加某個(gè)值,返回Set結(jié)構(gòu)本身
delete(values):刪除某個(gè)值,返回布爾值表示是否刪除成功
has(values):是否為Set的成員,返回布爾值
clear():清空所有成員,沒(méi)有返回值
遍歷方法
keys():返回鍵名的遍歷器
values():返回值的遍歷器
Set中沒(méi)有鍵值概念,所以keys和values方法行為完全一致,keys出來(lái)的是index,values出來(lái)的是對(duì)應(yīng)的值
entries():返回鍵值對(duì)的遍歷器
由于Set不像 Map 對(duì)象那樣擁有 key,為了與Map形式保持一致,每一個(gè) entry的 key 和 value 都擁有相同的值,因而最終返回一個(gè) [value, value] 形式的數(shù)組。
forEach():使用回調(diào)函數(shù)遍歷每個(gè)成員

let aa = [1,1,2,2,3,3,4,5,NaN,NaN,NaN,undefined,undefined,{},{}]
let s = new Set(aa)
for (let key of aa.keys()) {
   console.log(key);
}
for (let value of aa.values()) {
   console.log(value);
}
for (let entry of aa.entries()) {
   console.log(entry);
}

WeakSet

WeakSet和WeakMap一樣都是弱引用的數(shù)據(jù)結(jié)構(gòu),WeakSet是不重復(fù)的值的集合,他的成員只能是對(duì)象,而不能是其他類型的值。因?yàn)槭侨跻盟砸彩遣豢杀闅v的,只有add()、delete()、has()方法。

參考資料:

  1. ES6 系列之 WeakMap
  2. 阮一峰ECMAScript 6 入門
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容