ES6新增 Set
Set
(1)基本語法
Set是ES6新提供的一種資料結構,它類似於陣列,但是成員的值都是唯一的,沒有重複。
1.Set建構函式
Set本身是一個建構函式,Set函式接受具有iterator介面的資料結構作為引數,用來初始化。以陣列為例:
const set=new Set([1,1,2,2,3,4,5,5]);
console.log(set);
//Set [1,2,3,4,5]
可以看出Set結構不會新增重複的值。
2. 去除陣列重複成員的兩種方法
用擴充套件運算子(…)(擴充套件運算子內部使用for…of迴圈)可以將Set結構轉化為陣列:
const set=new Set([1,1,2,2,3,4,5,5]);
let a=[...set];
console.log(a);
//[1,2,3,4,5]
利用Array.from方法(將一個類陣列物件或者可遍歷物件轉換成一個真正的陣列):
let a=[1,1,2,3,3,4,4,5];
let set = new Set(a);
console.log(set);
//Set [1,2,3,4,5]
let b=Array.from(set);
console.log(b) ;
//[1,2,3,4,5]
3. 向Set加入值不發生型別轉換
向Set中加入值是是不發生型別轉換的,所以5和“5”是兩個不同的值:
const set=new Set(["5",5]);
console.log(set);
//Set ["5",5]
console.log(set.size);
//2
Set內部判斷兩個值是否相等用的演算法是"Same-value equality",類似於全等操作符(====),主要的區別是NaN等於自身。
我們先來複習一下全等操作符:它只在兩個運算元未經轉換就相等的情況下返回true,需要注意的是:
console.log(null===undefined);
//false
console.log(NaN===NaN);
//false
console.log({"1":"1"}==={"1":"1"});
//false 兩個物件記憶體地址不同,總是不全等的
console.log([1]===[1]);
//false 兩個陣列記憶體地址不同,總是不全等的
console.log({}==={});
//false 兩個空物件記憶體地址不同,總是不全等的
console.log([]===[]);
//false 兩個空陣列記憶體地址不同,總是不全等的
let c=function(){console.log("1")};
let d=function(){console.log("1")};
console.log(c===d);
//false 兩個函式記憶體地址不同,總是不全等的
let e=/at/g;
let f=/at/g;
console.log(e===f);
//false 兩個正則表示式記憶體地址不同,總是不全等的
let date1=new Date();
let date2=new Date();
console.log(date1===date2);
//false 兩個Date型別記憶體地址不同,總是不全等的
全等操作符進行比較時,物件(Date,Array,Obiect,RegExp,Function)通過指標指向的記憶體中的地址來做比較。
Set和全等操作符不同的地方在於,在Set內部認為NaN等於自身:
let set = new Set([NaN, NaN]);
console.log(set);
//Set [NaN]
console.log(set.size);
//1
Set和記憶體地址繫結,只要記憶體地址不同,就視為兩個值:
在Set中兩個物件,兩個陣列,兩個函式,兩個Date型別,兩個正則表示式總是不相等的:
//物件
let set = new Set([{"1":"1"}, {"1":"1"}]);
console.log(set.size);
//2
//陣列
let set1 = new Set([[1], [1]]);
console.log(set1.size);
//2
//空物件
let set3 = new Set([{}, {}]);
console.log(set3.size);
//2
//空陣列
let set4 = new Set([[], []]);
console.log(set4.size);
//2
//正則表示式
let e=/at/g;
let f=/at/g;
let set5 = new Set([e, f]);
console.log(set5.size);
//2
//Date型別
let date1=new Date();
let date2=new Date();
let set6 = new Set([date1, date2]);
console.log(set6.size);
//2
//函式
let c=function(){console.log("1")};
let d=function(){console.log("1")};
let set7 = new Set([c, d]);
console.log(set7.size);
//2
因為物件(Date,Array,Obiect,RegExp,Function)通過指標指向的記憶體中的地址來做比較。
(2)操作方法
1.add(value)
新增某個值,返回Set結構本身。
由於add方法返回Set結構本身,所以可以採用鏈式寫法:
let set = new Set();
set.add(1)
.add(2)
.add(3);
console.log(set);
// Set [1,2,3]
2.delete(value)
刪除某個值,返回一個布林值,表示刪除是否成功。
3.has(value)
返回一個布林值,表示引數是否為Set成員。
4.clear()
清除所有成員,沒有返回值。
(3)遍歷操作
Set的遍歷順序就是插入順序,在Map中遍歷順序也是插入順序。
1.keys():返回鍵名的遍歷器。
2.values():返回鍵值的遍歷器。
3.entries():返回鍵值對的遍歷器。
由於Set結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),所以keys方法和values方法的行為完全一致。
let set = new Set([1, 2, 3]);
for (let item of set.keys()) {
console.log(item)
}
//1
//2
//3
for (let item of set.values()) {
console.log(item)
}
//1
//2
//3
for (let item of set.entries()) {
console.log(item)
}
//[1,1]
//[2,2]
//[3,3]
for (let item of set) {
console.log(item)
}
//1
//2
//3
由上面第四個for…of迴圈可看出,Set結構的例項預設可遍歷,預設遍歷器生成函式就是它的values方法(在Map結構中預設遍歷器介面是entries方法)。
4.forEach():使用回撥函式遍歷每個成員,沒有返回值。
let set = new Set([1, 2, 3]);
set.forEach((value, key) => {
console.log(value * 2)
})
//2
//4
//6
遍歷方法的應用
1.Set本身沒有map和filter方法,可以轉為陣列,之後使用陣列的map和filter方法:
let set = new Set([1, 2, 3]);
let set1=new Set([...set].map(x=>x*2));
console.log(set1);
//Set [2,4,6]
let set2=new Set([...set].filter(x=>(x%2===0)));
console.log(set2);
// Set [2]
2.實現並集、交集和差集:
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
//並集
let set1 = new Set([...a,...b]);
console.log(set1);
//Set [1,2,3,4]
//交集
let set2 = new Set([...a].filter(x => b.has(x)));
console.log(set2);
// Set [2,3]
//差集
let set3 = new Set([...a].filter(x => !b.has(x)));
console.log(set3);
// Set [1]