作為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
型別的2
和String
型別的 '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)}
複製程式碼
上面的例子說明陣列的成員只能是物件
總結
Set
和 WeakSet
的關係類似於 Map
和 WeakMap
的關係,想要了解 Map
資料結構,可以看另外一篇文章 連結: ES6 Map 資料結構