computed get set 传参_ES6 的 Set 与 Map深入理解
Set 和 Map 出現(xiàn)之前
在 ES5 中經(jīng)常用對象來模擬實現(xiàn) Set 集合與 Map 集合這兩種數(shù)據(jù)結(jié)構(gòu),但這種做法帶來了一些問題:比如利用?if(obj.size)?檢查集合中是否存在某個元素的時候,預(yù)期行為是只要存在?size?就能通過 if 判斷,但如果?size = 0,那么也無法繼續(xù)執(zhí)行,即使此時元素是存在的。另外,對象的鍵名只能是字符串,非字符串類型的鍵名也會通過?toString()?方法被轉(zhuǎn)換成字符串,這意味著?obj[5]?與?obj['5']?沒有區(qū)別,盡管我們本意是想創(chuàng)建兩個不同的鍵;甚至,當(dāng)鍵名是對象的時候,不管我們操作的是哪個鍵名(obj[key1]?或者?obj[key2]),實際操作的都是?obj['[object Object]'],這是因為對象會被轉(zhuǎn)換成字符串?'[object Object]',這些都是與我們的預(yù)期不符合的。因此,ES6 推出了正式的 Set 和 Map 集合。
Set
調(diào)用?new Set()?可以創(chuàng)建一個 Set 集合,之后通過?add()?添加元素,size?訪問元素數(shù)量。
let set = new Set()set.add('one')
set.add('two')
set.size // 2
與 ES5 中對象模擬實現(xiàn)不同的是,Set 集合會對添加進(jìn)來的元素調(diào)用Object.is()?檢查是否一致,由于?5?與?'5'?是不同的,所以 Set 可以同時存在這兩個元素,不會發(fā)生類型轉(zhuǎn)換(唯一的例外是?+0?和?-0,盡管?Object.is(+0,-0)?返回?false,但是 Set 集合認(rèn)為這兩個是一致的);同理,也可以添加多個獨立對象,它們是不會被轉(zhuǎn)換成字符串的。
set.add(5)set.add('5')
let key1 = {}
let key2 = {}
set.add(key1)
set.add(key2)
set.size // 4
還可以用?has()?檢測是否存在某個元素,用?delete()?移除指定元素,用?clear()?清空整個 Set 集合。
另外,創(chuàng)建 Set 集合的時候支持傳參,我們可以使用像數(shù)組這樣的可迭代對象來初始化 Set 集合(這也是將數(shù)組轉(zhuǎn)換成 Set 集合的方法):
let set = new Set([1,2,2,3,4])set.size // 4
注意:Set 集合為了保證集合元素唯一,會對數(shù)組進(jìn)行元素過濾,這一點稍后可以用來進(jìn)行數(shù)組去重。
那么如何訪問集合元素呢?由于 Set 集合沒有鍵名,所以不可能像數(shù)組那樣通過數(shù)值型索引值去訪問某個元素,要訪問 Set 集合的元素,我們需要先將集合轉(zhuǎn)換成數(shù)組。這個使用展開運算符?...?來實現(xiàn):
let set = new Set()set.add(1)
set.add(2)
let array = [...set]
array // [1,2]
數(shù)組轉(zhuǎn)換成集合+集合轉(zhuǎn)換成數(shù)組,就可以實現(xiàn)數(shù)組去重:
let array = [1,2,2,3,4,5,6,6]let anotherArray = [...new Set(array)] // [1,2,3,4,5,6]
此外,可以用?forEach()?來迭代 Set 集合中的元素,該方法的回調(diào)函數(shù)接受三個參數(shù):value,key?以及集合本身。雖然 Set 沒有?key?鍵名,但為了與數(shù)組和Map?的?forEach()?保持一致,依然提供了?key?參數(shù),它的值與?value?是一樣的。
Weak Set
上面的 Set 是一個強(qiáng)引用的集合,這指的是,如果集合中存儲著對象的引用(set.add(obj)),那么即使我們已經(jīng)在集合外面清除了對該對象的引用(obj = null),集合中的引用也不受影響。為了避免造成內(nèi)存泄漏,我們需要一種弱引用的集合,也就是 Weak Set。
Weak Set 只存儲對象的弱引用,所以如果把集合外面對象的最后一個強(qiáng)引用移除,則 Weak Set 中的引用也不復(fù)存在,這樣就避免了內(nèi)存泄露的情況。此外,它還有一些特點:
- 不可以存儲原始值,否則報錯
- 不可迭代,所以不能使用?forEach(),clear()
- 不支持?size?屬性
- 不暴露諸如?keys(),values()?等迭代器
Map
相比 Set,Map 存儲的是多對鍵值對,并且鍵名和鍵值支持所有的數(shù)據(jù)類型。
調(diào)用?new Map()?可以創(chuàng)建一個 Map 集合,之后通過?map.set(key,value)?添加鍵值對,map.get(key)?訪問指定鍵名的鍵值。
let map = new Map()let obj = {}
map.set('name','Jack')
map.set(obj,'I am object') // 不同于對象,在 Map 中鍵名可以是對象
map.get('name') // 'Jack'
map.get(obj) // 'I am object'
map.get('unexisted key') // 訪問不存在的鍵,返回 undefined
Map 同樣也有?has(key),delete(key),clear(),size?(返回鍵值對對數(shù))等方法和屬性。
另外,可以使用數(shù)組來初始化 Map 集合,批量添加元素。由于 Map 中的元素是鍵值對,所以傳入的數(shù)組的元素也是數(shù)組:
let map = new Map([['name','Jack'],['age',12]])map.get('name') // 'Jack'
map.get('age') // 12
map.size // 2
Map 的?forEach()?方法的回調(diào)函數(shù)也接受三個參數(shù):value,key?以及集合本身,這和數(shù)組更為接近,只不過數(shù)組對應(yīng)的第二個參數(shù)是數(shù)值型索引值。
Weak Map
類似的,Map 也有弱引用集合 Weak Map。Weak Map 的鍵名必須是對象,且保存著對象的弱引用(如果集合外面引用被清除,則集合中的引用也不復(fù)存在,且鍵值對會跟著被移除);鍵值則不一定是對象,且當(dāng)鍵值是對象時,它保存的依然是強(qiáng)引用。也就是說,Weak Map 的弱引用是針對鍵名來說的。
Weak Map 可以用來跟蹤對象的引用,進(jìn)而確保將來某一刻需要清除的對象的內(nèi)存一定能夠得到釋放,不發(fā)生潛在的內(nèi)存泄露。
舉例來說,現(xiàn)在有一個 DOM 元素,它接受用戶的輸入并將輸入的信息存儲在一個對象中,如果沒有使用 Weak Map ,那么維系?DOM 對象?與?輸入信息對象?的映射關(guān)系時就有可能產(chǎn)生一個新的關(guān)于 DOM 對象的強(qiáng)引用,而在之后清除 DOM 對象原先的強(qiáng)引用時,該強(qiáng)引用可能不會被清除,這導(dǎo)致對象內(nèi)存實際沒有得到釋放。但是,如果使用了 Weak Map,將 DOM 對象作為鍵名,輸入信息對象作為鍵值,那么由于 Weak Map 存儲的是對象的弱引用,此時就一定能保證 DOM 對象被移除后(且集合外圍對象的最后一個強(qiáng)引用被清除),其內(nèi)存能夠得到釋放,不會發(fā)生內(nèi)存泄露的問題。
此外,Weak Map 也可以用來存儲對象實例的私有變量:
let Person = (function(name,age){let privateData = new WeakMap()
function Person(){
privateData.set(this,{name:name,age:age})
}
Person.prototype.getName = function(){
return privateData.get(this).name
}
Person.prototype.getAge = function(){
return privateData.get(this).age
}
}())
在上面的這段代碼中,存在著一個 Weak Map(privateData)用來維系多個實例與自身私有變量的映射關(guān)系。每次創(chuàng)建新實例的時候,都會往 privateData 這個集合中添加新的”映射條目“(privateData.set(this,{name:name,age:age}),其中,this?指的是實例),鍵名是實例,鍵值是存儲私有變量的對象。這么一來,當(dāng)未來某一天刪除實例的時候,由于集合外圍的實例對象的強(qiáng)引用被移除,Weak Map 存儲的又是實例對象的弱引用,所以保證了實弱引用也會被垃圾回收,不存在內(nèi)存泄漏的問題。簡而言之,只要實例被銷毀,相關(guān)信息也會跟著銷毀,這樣就保證了信息的私有性。
此外,Weak Map 還有一些特點:
- 不支持?size?屬性
- 不可迭代,因此不支持?forEach()?和?clear()
點個「在看」,讓更多的人也能看到這篇內(nèi)容。
關(guān)注「前端人」,第一時間接收原創(chuàng)、精選干貨文章,讓你的技能樹加速點滿!
[關(guān)注我們,加群一起學(xué)習(xí)]
總結(jié)
以上是生活随笔為你收集整理的computed get set 传参_ES6 的 Set 与 Map深入理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sql求平均日活_杨学峰博客 | Fla
- 下一篇: 电信业务分类目录2019_2019年1月