ES6 新增數(shù)據(jù)結(jié)構(gòu),太強(qiáng)了,值得學(xué)習(xí)
大家好,我是前端人,每日分享前端相關(guān)內(nèi)容!
今天給大家介紹下 ES6 中的 Map、WeakMap、set 和 WeakSet 的詳細(xì)使用,以及它們的區(qū)別!
本篇文章知識(shí)點(diǎn)總結(jié)如下:
一、Set
ES6 中提供新的數(shù)據(jù)結(jié)構(gòu) Set 集合,它類似于數(shù)組,但成員的值都是唯一的,集合類似于高中所學(xué)的集合,概念是一致的。集合實(shí)現(xiàn)了 iterator 接口,所以他可以使用擴(kuò)展運(yùn)算符進(jìn)行展開,也可以使用 for...of 進(jìn)行遍歷。
set 使用:
let s = new Set([ '年終獎(jiǎng)是大事', '放假是好事', '放假是好事' ]);
console.log( s ) // set(2) { '年終獎(jiǎng)是大事', '放假是好事' }
console.log( typeof s ) // object
new Set 返回的數(shù)據(jù)是一個(gè)對(duì)象,它是自動(dòng)去掉重復(fù)項(xiàng)。
集合的屬性和方法分別有:
- size :返回集合元素的個(gè)數(shù)
- add :增加一個(gè)新元素
- delete:刪除某個(gè)元素,返回布爾值
- has :檢測(cè)集合中是否包含某元素
- clear:清空集合
Set 的常見應(yīng)用:
數(shù)組去重:
let arr = [ 1,2,3,4,3,2,1 ]
let res = [ ...new Set(arr) ]
console.log( res ) //[1, 2, 3, 4]
取兩個(gè)集合的交集
let arr1 = [ 1,2,3,4,3,2,1 ]
let arr2 = [ 1,2 ]
let res = [...new Set(arr1)].filter( item=>new Set(arr2).has(item) )
console.log( res ) //[1, 2]
取兩個(gè)集合的并集
let arr1 = [ 1,2,3,4,3,2,1 ]
let arr2 = [ 1,2 ]
let res =[ ...new Set([...arr1, ...arr2]) ]
console.log(res ) //[ 1, 2, 3, 4 ]
取差集
let arr1 = [ 1,2,3,4,3,2,1 ]
let arr2 = [ 1,2 ]
let res = [...new Set(arr1)].filter( item=>!new Set(arr2).has(item) )
console.log( res ) //[ 3, 4 ]
Set 數(shù)據(jù)遍歷:
let s1 = new Set()
s1.add("碧根果")
s1.add("夏威夷果")
for(let v of s1){
console.log("v",v)
}
/*
v 碧根果
v 夏威夷果
*/
Set 遍歷的方式有很多,我只介紹 for...of ,剩余的可自行查找!
二、Map
ES6 提供了 Map 數(shù)據(jù)結(jié)構(gòu),它類似于對(duì)象,也是鍵值對(duì)的集合,但是鍵的范圍不限于字符串,各種類型的值(包括對(duì)象)都可以當(dāng)做鍵,Map 也實(shí)現(xiàn)了 iterator 接口,所以也可以使用 for...of 進(jìn)行遍歷,使用擴(kuò)展運(yùn)算符展開數(shù)據(jù)。
Map 的使用:
let m= new Map()
m.set( "name", "我是前端人" )
let key = {
job: "前端工程師"
}
m.set( key, [ "運(yùn)營(yíng)", "設(shè)計(jì)" ] )
console.log(m)
運(yùn)行結(jié)果如圖:
集合的屬性和方法:
- size :返回集合元素的個(gè)數(shù)
- set:給 Map 添加鍵值對(duì)。
- get:從 Map 中提取值。
- delete:刪除某個(gè)元素,返回布爾值
- has :檢測(cè)集合中是否包含某元素
- clear:清空集合
Map 的遍歷
let map = new Map([['title','hello world'],['year','2022']]);
map.forEach((value,key,ownerMap)=>{
console.log(value);
console.log(key);
});
hello world
title
2022
year
Map 的應(yīng)用
假設(shè)有一個(gè)場(chǎng)景,我們需要存儲(chǔ) DOM 節(jié)點(diǎn)的屬性以及它的值,我們可能會(huì)用到 Object 或者 Map 。在這選擇 Map
const m = new Map()
const loginBtn = document.querySelector("#login")
m.set( loginBtn, { disabled: true } )
這樣應(yīng)用的時(shí)候會(huì)產(chǎn)生一個(gè)問題:當(dāng)用戶登錄之后,跑到另一個(gè)界面,登錄按鈕被移除,正常來(lái)說,這個(gè) DOM 節(jié)點(diǎn)應(yīng)該被垃圾回收清除,但是它被 loginBtn 變量引用,loginBtn 作為 key 被 Map 引用,所以登錄 DOM 節(jié)點(diǎn)會(huì)保留在內(nèi)存中,白白占用空間。此時(shí)就需要引入 WeakMap 。
三、WeakMap
WeakMap 的 key 只能是 Object 實(shí)例化的對(duì)象或者派生類的對(duì)象,如果不是的話,則會(huì)報(bào)錯(cuò),WeakMap 對(duì)象的 value 值 可以是任意類型數(shù)據(jù)。
WeakMap 使用
let wm = new WeakMap()
wm.set( {},'value' )
弱鍵:WeakMap 的 key 都是對(duì)象或者派生類的對(duì)象,目的是為了讓這個(gè) key 被弱持有。這些對(duì)象都是弱引用,不會(huì)干擾到垃圾回收。當(dāng) WeakMap 中的鍵在 WeakMap 之外不存在引用時(shí),該鍵值對(duì)會(huì)被移除。
Map 中的實(shí)例把 Map 替換成 weakMap:
const vm = new WeakMap()
const loginBtn = document.querySelector("#login")
vm.set( loginBtn, { disabled: true } )
作為 WeakMap 對(duì)象的 key 不會(huì)被正式引用,也就是說 loginBtn 變量不被 vm 引用,這時(shí)垃圾回收器就可以把這個(gè) loginBtn 變量和登錄DOM節(jié)點(diǎn)都給干掉,釋放內(nèi)存空間。
WeakMap 的 key 不算正式引用,隨時(shí)可以被回收清除掉,因此 WeakMap 不提供迭代功能。對(duì)于 size 屬性和 clear 方法,由于它們需要先迭代遍歷所有的 key 才能計(jì)算得到,所以 size 和 clear 無(wú)法使用。
WeakMap 的 API 與 Map 對(duì)象基本都是一樣的,除了沒有 size 屬性和 clear 方法。
四、WeakSet
WeakSet 對(duì)于 Set 而言,就像 WeakMap 對(duì)于 Map 一樣。
在存放對(duì)象時(shí),實(shí)際上是存放的是對(duì)象的引用,即 Set 也被稱之為 Strong Set 。如果所存儲(chǔ)的對(duì)象被置為 null ,但是 Set 實(shí)例仍然存在的話,對(duì)象依然無(wú)法被垃圾回收器回收,從而無(wú)法釋放內(nèi)存。
let set = new WeakSet();
let key = {};
set.add(key);
console.log(set.has(key)); //true
set.delete(key);
console.log(set.has(key)); //false
注意:WeakSet 構(gòu)造器不接受基本類型的數(shù)據(jù),只接受對(duì)象。同樣的可以使用可迭代的對(duì)象或數(shù)組,來(lái)作為構(gòu)造器參數(shù),來(lái)創(chuàng)建 WeakSet 。
WeakSet 的 API 與 Set 對(duì)象基本都是一樣的,除了沒有 size 屬性和 clear 方法。
五、總結(jié)之間的區(qū)別
5.1、對(duì)于 WeakSet 和 Set 之間的區(qū)別:
WeakSet 沒有 size 和 clear 。
- WeakSet 無(wú)法暴露出任何迭代器。
- WeakSet 不可迭代,因此不能使用 for...of 遍歷
- WeakSet 實(shí)例,弱調(diào)用了 add 方法時(shí)傳入非對(duì)象參數(shù),會(huì)拋出異常。在 has 和 delete 方法傳入非對(duì)象的參數(shù)返回 false。
對(duì)于 WeakMap 和 Map 之間的區(qū)別與上邊 WeakSet 和 Set 的區(qū)別類似。不再贅述。
5.2、Set 與 Map 之間的共性及區(qū)別:
- Set 和 Map 都是一種數(shù)據(jù)結(jié)構(gòu),但是 Set 是一個(gè)無(wú)重復(fù)的有序列表,類似于數(shù)組,而 Map 是有序的鍵值對(duì)集合,類似于對(duì)象。
- 都將通過 Object.is() 方法來(lái)判斷其中的值不相等,保證 Set 和 Map 移除重復(fù)值。Set 無(wú)法隨機(jī)訪問其中的值,只能通過 has 判斷某個(gè)值是否存在。而 Map 使用 get 提取任意鍵對(duì)應(yīng)的數(shù)據(jù)。
- Map 和 Set 都可以隨意的實(shí)例中添加數(shù)據(jù),Set 使用的是 add ,而 Map 使用的 set 方法。其他的 API 都相同。