- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > web開(kāi)發(fā) > JavaScript >
- ES6中Set與WeakSet集合的深入講解
每天都用數組,有沒(méi)有過(guò)一個(gè)Moment,擔心插入了重復的值?使用Set集合吧!Set擁有特殊的數據結構,保證插入的值永遠不會(huì )重復。
通過(guò)Set.prototype.constructor 構造函數創(chuàng )建Set實(shí)例
/* * 僅實(shí)例化:調用構造函數,不傳參數 */ let empty_set = new Set() /* * 實(shí)例化同時(shí)初始化:傳入任意iterate對象,將其轉換成Set集合 */ let transfer_set4arr = new Set([1, 2, 3]) // 返回Set(3) {1, 2, 3} let transfer_set4string = new Set("huilin") // 返回Set(5) {"h", "u", "i", "l", "n"} let transfer_set4set = new Set(new Set([5, 6])) // 返回Set(2) { 5, 6 }
訪(fǎng)問(wèn) Set.prototype.size屬性,返回集合中元素的個(gè)數
console.log(empty_set.size) // 0 console.log(transfer_set4arr.size) // 3
調用 Set.prototype.has(value) 方法,判斷元素是否存在
// 相比起Array.includes(),Set.has()性能更高,因為專(zhuān)門(mén)對成員測試進(jìn)行了優(yōu)化 console.log(empty_set.has(1)) // false console.log(transfer_set4arr.has('h')) // true
想了解更多關(guān)于Object.is(),請跳轉查看:…
let n1 = NaN let n2 = NaN console.log(n1 === n2) // 恒等符號判斷兩者不一致,輸出false console.log(Object.is(n1,n2)) // 但Object.is()判斷兩者是相同的,輸出false // Set集合不允許將兩個(gè)NaN放入集合 let set = new Set() set.add(n1).add(n2) console.log(set.size) // size: 1
而面對復雜數據類(lèi)型時(shí),主要通過(guò)對象的引用進(jìn)行判斷。引用不一致,即便數據結構一致,也認為只不相同,因此能存入Set集合。
let same_value_set = new Set(); // 先存入一個(gè)對象 same_value_set.add({num: 0}); // 再存入一個(gè)結構一致的新對象 let obj = {num: 0}; same_value_set.add(obj); // 都能存入成功 console.log(same_value_set.size); // 2
調用Set.prototype.add(value) 方法,向集合追加數據
// add()方法可以追加任意類(lèi)型的數據,不論是原始值或者是對象引用 let set1 = new Set() // 由于add()方法始終返回當前實(shí)例的引用,所以進(jìn)行鏈式調用 set1.add(1).add(2).add(3) console.log(set1) // Set(3) {1, 2, 3} // 注意:當add()傳入數組時(shí),Set會(huì )將數組實(shí)例插入集合,而不是數組內的元素 set1.add([4, 5]) console.log(set1) // Set(4) {1, 2, 3, [4, 5]}
調用Set.prototype.delete(value) 方法,移除集合中的元素
// delete()方法返回移除操作是否成功,與.has()方法一樣 let success = set1.delete(1) console.log(success) // true
調用Set.prototype.clear() 方法,清空集合
let num_set = new Set([1, 6, 3]) console.log(num_set) // Set(3) { 1, 6, 3 } set1.clear() console.log(num_set) // Set(0) {}
由于集合沒(méi)有下標/索引,通常被認為是“無(wú)序集合”。但JavaScript會(huì )記住元素插入的順序,所以遍歷的時(shí)候也按順序對元素進(jìn)行迭代。
直接遍歷Set集合
let set = new Set([1, 2, 3, 4, 5]) for(let item of set){ console.log(item) } // 依次輸出:1 2 3 4 5
創(chuàng )建迭代器進(jìn)行遍歷
/* * 創(chuàng )建迭代器的有三種方式 * Set.prototype.entries() * Set.prototype.keys() * Set.prototype.values() */ // Set集合只有value而沒(méi)有key,但為了使得和遍歷Map對象相似,Set.entries()創(chuàng )建新的Iterator對象時(shí),每一項的鍵和值都相等,即[value,value] for(let [key,value] of set.entries()){ console.log(value) } // 依次輸出:1 2 3 4 5 // Set.keys()創(chuàng )建新的Iterator對象,返回每一項值 for(let key of set.keys()){ console.log(key) } // 依次輸出:1 2 3 4 5 // Set.values()和Set.keys()一致,返回每一項的值 for(let value of set.values()){ console.log(value) } // 依次輸出:1 2 3 4 5
調用Set.prototype.forEach(callbackFn)方法遍歷
// forEach(callbackFn) 按照插入順序調用callbackFn,取出每項值 set.forEach(item => { console.log(item) }) // 依次輸出:1 2 3 4 5
/* * Set轉Array */ let set1 = new Set([1, 2, 3]) // Array.from()方法 let arr1 = Array.from(set1) // 擴展運算符 let arr2 = [...set1] /* * Array轉Set */ // 利用Set構造函數 let set = new Set(array)
let set = new Set([1, 2, 4, 4, 2, 5]) console.log(set) // Set(4) { 1, 2, 4, 5 }
let arr1 = [1, 2, 4] let arr2 = [1, 5, 6] // 利用Set集合的特性,集合內的元素都是唯一的 let result = new Set([...set1, ...set2]) console.log(result) // Set(5) { 1, 2, 4, 5, 6 }
let set1 = new Set([1, 2, 4]) let set2 = new Set([1, 5, 6]) // 返回set1和set2都存在的元素 let result = new Set([...set1].filter(x => set2.has(x))) console.log(result) // Set(1) { 1 }
let set1 = new Set([1, 2, 4]) let set2 = new Set([1, 5, 6]) function isMixed(set, subset) { for (let elem of subset) { if (set.has(elem)) { return true; } } return false; } console.log(isMixed(set1, set2)) // true
let set1 = new Set([1, 2, 4]) let set2 = new Set([1, 5, 6]) function difference(setA, setB) { let result = new Set() for (let elem of setB) { if(setA.has(elem)){ result.add(elem) } } return result; } console.log(difference(set1, set2))
除了Set集合外,ES6還提供了WeakSet和WeakMap。既然集合的名字都叫“Weak(弱)的集合”了,究竟它“弱”在哪里呢?
WeakSet不允許插入原始值,僅支持對象的引用;
let val1 = {id: 1}, val2 = {id: 2} let ws = new WeakSet() // 和Set集合一樣,WeakSet的值也不重復,同時(shí)add()也返回集合實(shí)例,所以可以鏈式操作 ws.add(val1).add(val1).add(val2) // 不允許插入基礎數據類(lèi)型 ws.add(3) // 報錯:TypeError:Invalid value used in WeakSet // 但可以先包裝成對象后再插入 let val3 = new Number(3) ws.add(val3) console.log(ws.has(val3)) // 輸出:true
要說(shuō)弱引用,先看看什么是強引用:
// 聲明一個(gè)對象 let handsome = { name: 'huilin', age: 30 } // 放入數組 let arr = [1, handsome, 2] console.log('release before arr length', arr.length) // 3 // 放入Map let user = { oid: 10001, classify: 'Chinese', staffReference: handsome } console.log('release before map length', Object.keys(user).length) // 3 console.log('----') // 突然把對象置為null handsome = null // 強引用的容器中,對象仍然存在沒(méi)有被回收 console.log('release after arr length', arr.length) // 3 console.log(arr[1]) // { name: 'huilin', age: 30 } console.log('release after map length', Object.keys(user).length) // 3 console.log(user.staffReference) // { name: 'huilin', age: 30 }
從測試代碼看出,除非容器銷(xiāo)毀,否則引用的對象一直沒(méi)有被回收。而所謂弱引用,就是希望容器是根據元素自動(dòng)伸縮的,一旦對象為null,容器中的引用也跟著(zhù)回收。
let obj1 = { name: 'huilin', age: 30 } let obj2 = { name: 'cc', age: 29 } let ws1 = new WeakSet() ws1.add(obj1).add(obj2) console.log(ws1.has(obj1)) // true // 不管是從容器操作元素 ws1.delete(obj1) console.log(ws1.has(obj1)) // false // 或者是對象自己置為null,都會(huì )自動(dòng)回收 obj2 = null console.log(ws1.has(obj2)) // false
Reference
到此這篇關(guān)于ES6中Set與WeakSet集合的文章就介紹到這了,更多相關(guān)ES6 Set與WeakSet集合內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站