ES6 Set 資料結構

閃現A小兵發表於2020-02-26

作為ES6提供的一種新資料結構, Set 類似於陣列,但其成員卻是唯一的,不會有重複的成員出現.Set 本身是一個建構函式,可以生成Set資料結構

例項化

  • 方法1
// 接受陣列作為引數
const arr = [1,2,3]
const s0 = new Set(arr)
console.log(s0)  //Set(3) {1, 2, 3}
複製程式碼
  • 方法2
// html
<span>1</span>
<span>2</span>
<span>3</span>
複製程式碼
// 接受類似陣列的物件作為引數
const spans = document.querySelectorAll('span')
console.log(spans)
console.log(new Set(spans))  //Set(3) {span, span, span}

複製程式碼
  • 方法3
// 例項化後通過add()方法新增元素
const s = new Set()
s.add(1).add(2).add(2).add('2')
console.log(s) //Set(3) {1, 2, "2"}
複製程式碼

由此還可以看出來Number型別的2String型別的 '2'是不一樣的.Set內部判斷兩個值是否相等的演算法類似於 全等運算子( === ) ,最主要的區別在於Set裡面 NaN等於自身, 但是 === 比較中認為 NaN !== NaN,這個從下面的程式碼中可以看出來

s.add(NaN)
console.log(s)  //Set(4) {1, 2, "2", NaN}
s.add(NaN)
console.log(s)  //Set(4) {1, 2, "2", NaN}
複製程式碼

第二次add(NaN)之後再次列印set的資料結構,發現沒有變化,印證了上面的結論

例項方法

操作方法

  • add(value) 說明: 新增值,返回Set本身,因此add可以鏈式呼叫
  • delete(value) 說明: 刪除值,返回一個Boolean表示刪除是否成功
  • has(value) 說明: 表示是否有這個成員,返回Boolean型別
  • clear() 說明: 清除所有成員
add()
const s2 = new Set()
s2.add(1).add(2)
console.log(s2)  //Set(2) {1, 2}
複製程式碼
delete()
const isSuccess = s2.delete(2)
console.log(isSuccess)  //true
console.log(s2)  //Set(1) {1}
複製程式碼
has()
console.log(s2.has(1))  //true
console.log(s2.has(2))  //false
複製程式碼
clear()
s2.clear()
console.log(s2)  //Set(0) {}
複製程式碼

遍歷方法

  • keys() 說明: 返回鍵名
  • values() 說明: 返回鍵值
  • entries() 說明: 返回鍵值對
  • forEach() 說明: 使用回撥遍歷每個成員
keys()
const nameArr = ['zhangsan','lisi','wangwu']
const nameSet = new Set(nameArr)
console.log(nameSet.keys())  //SetIterator {"zhangsan", "lisi", "wangwu"}
for(let item of nameSet.keys()){
  console.log(item)
}
// zhangsan
// lisi
// wangwu
複製程式碼
values()
console.log(nameSet.values())  //SetIterator {"zhangsan", "lisi", "wangwu"}
for(let item of nameSet.values()){
  console.log(item)
}
// zhangsan
// lisi
// wangwu
複製程式碼
entries()
console.log(nameSet.entries())  //SetIterator {"zhangsan" => "zhangsan", "lisi" => "lisi", "wangwu" => "wangwu"}
for(let item of nameSet.entries()){
  console.log(item)
}
// ["zhangsan", "zhangsan"]
// ["lisi", "lisi"]
// ["wangwu", "wangwu"]
複製程式碼
for(let item of nameSet){
  console.log(item)
}
// zhangsan
// lisi
// wangwu
複製程式碼

例項預設就可以被遍歷,預設的就是values()方法

forEach()
nameSet.forEach((v,k) => console.log('key: %s, value: %s',k,v))
// key: zhangsan, value: zhangsan
// key: lisi, value: lisi
// key: wangwu, value: wangwu
複製程式碼

Set實現陣列去重

  • 方法1
const tmpArr = [1,2,2,3]
console.log([...new Set(tmpArr)])  // [1, 2, 3]
複製程式碼
  • 方法2
const tmpArr = [1,2,2,3]
console.log(Array.from(new Set(tmpArr)))  // [1, 2, 3]
複製程式碼

WeakSet

WeakSet()的成員只能是物件,而不能是其他的資料型別,這是它與Set()的第一點區別

const wSet = new WeakSet()
console.log(wSet)  // WeakSet {}

try{
  wSet.add(1) 
}catch(e){
  console.warn(e)  //TypeError: Invalid value used in weak set
}

wSet.add({}) 
console.log(wSet)  //WeakSet {{…}}
複製程式碼

第二點區別是WeakSet中物件都是弱引用,垃圾回收機制不考慮WeakSet對該物件的引用,因此WeakSet也是不可遍歷的

const wArr = [3,4]
try{
  console.log(new WeakSet(wArr))  //TypeError: Invalid value used in weak set
}catch(e){
  console.warn(e)
}

const wArr2 = [[1],[2]]
console.log(new WeakSet(wArr2)) //WeakSet {Array(1), Array(1)}
複製程式碼

上面的例子說明陣列的成員只能是物件

總結

SetWeakSet 的關係類似於 MapWeakMap 的關係,想要了解 Map 資料結構,可以看另外一篇文章 連結: ES6 Map 資料結構

相關文章