### Set數據結構
* Set
* WeakSet
* Map
* WeakMap
* * * * *
#### Set
> ES6新增了一個Set數據結構。它類似于數組,但是成員的值都是唯一的,沒有重復的值。Set 本身是一個構造函數,用來生成 Set 數據結構。Set構造函數可以接收一個數組或者類似數組的對象來作為參數,用于初始化。
> 向Set加入值的時候,不會發生類型轉換,所以5和"5"是兩個不同的值。Set內部判斷兩個值是否不同,使用的算法叫做“Same-value equality”,它類似于精確相等運算符(===),主要的區別是NaN等于自身,而精確相等運算符認為NaN不等于自身。注意??:***在Set內部,兩個NaN是相等。另外,兩個對象或數組(數組也是對象)總是不相等的。***
> 案例如下:
~~~
let s = new Set([1, 2, 3, 4, 4]);
console.log(s) // [1,2,3,4]
// 因為Set數據結構不允許內部有重復值
~~~
> Set結構的實例有以下屬性:
> Set.prototype.constructor:構造函數,默認就是Set函數。
Set.prototype.size:返回Set實例的成員總數。
~~~
let s = new Set([1, 2, 3, 4, 4]);
console.log(s.size) // 4
~~~
> Set實例的方法分為兩大類:操作方法(用于操作數據)和遍歷方法(用于遍歷成員)。下面先介紹四個操作方法:
> add(value):添加某個值,返回Set結構本身。
delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
has(value):返回一個布爾值,表示該值是否為Set的成員。
clear():清除所有成員,沒有返回值。
> 數組的Array.from方法可以將Set結構轉為數組。那么就可以通過該方法來為數組去重了;如下:
~~~
let wtf = ["andy","tom","jack","andy"]
//注意這個數組中有兩個"andy"
let hhh = Array.from(new Set(wtf))
console.log(hhh) //["andy","tom","jack"]
~~~
#### WeakSet
> WeakSet結構與Set類似,也是不重復的值的集合。但是,它與Set有兩個區別。
首先,WeakSet的成員只能是對象,而不能是其他類型的值。
其次,WeakSet中的對象都是弱引用,即垃圾回收機制不考慮WeakSet對該對象的引用,也就是說,如果其他對象都不再引用該對象,那么垃圾回收機制會自動回收該對象所占用的內存,不考慮該對象還存在于WeakSet之中。這個特點意味著,無法引用WeakSet的成員,因此WeakSet是不可遍歷的
> WeakSet是一個構造函數,可以使用new命令,創建WeakSet數據結構。
> 作為構造函數,WeakSet可以接受一個數組或類似數組的對象作為參數。該數組的所有成員,都會自動成為WeakSet實例對象的成員。
~~~
let a = [[1,2], [3,4]];
let s = new WeakSet(a);
console.log(s) //WeakSet {[1, 2], [3, 4]}
~~~
> WeakSet結構有以下三個方法:
* WeakSet.prototype.add(value):向WeakSet實例添加一個新成員。
* WeakSet.prototype.delete(value):清除WeakSet實例的指定成員。
* WeakSet.prototype.has(value):返回一個布爾值,表示某個值是否在WeakSet實例之中。
#### Map
> JavaScript的對象(Object),本質上是鍵值對的集合(Hash結構),但是傳統上只能用字符串當作鍵。這給它的使用帶來了很大的限制。為了解決這個問題,ES6提供了Map數據結構。它類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當作鍵。也就是說,Object結構提供了“字符串—值”的對應,Map結構提供了“值—值”的對應,是一種更完善的Hash結構實現。如果你需要“鍵值對”的數據結構,Map比Object更合適。
作為構造函數,Map也可以接受一個數組作為參數。該數組的成員是一個個表示鍵值對的數組。
> Map的鍵實際上是跟內存地址綁定的,只要內存地址不一樣,就視為兩個鍵。這就解決了同名屬性碰撞(clash)的問題,我們擴展別人的庫的時候,如果使用對象作為鍵名,就不用擔心自己的屬性與原作者的屬性同名。
> 如果Map的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map將其視為一個鍵,包括0和-0。另外,雖然NaN不嚴格相等于自身,但Map將其視為同一個鍵。
案例如下:
~~~
let ma = new Map([['name', 'andy'],['title', 'haha']]);
console.log(ma) //Map {"name" => "andy", "title" => "haha"}
~~~
> Map結構的實例有以下屬性和操作方法:
* size屬性返回Map結構的成員總數。
* set()方法設置key所對應的鍵值,然后返回整個Map結構。如果key已經有值,則鍵值會被更新,否則就新生成該鍵。set方法返回的是Map本身,因此可以采用鏈式寫法。
* get()方法讀取key對應的鍵值,如果找不到key,返回undefined。
* has()方法返回一個布爾值,表示某個鍵是否在Map數據結構中。
* delete方法刪除某個鍵,返回true。如果刪除失敗,返回false。
* clear方法清除所有成員,沒有返回值。
> Map原生提供三個遍歷器生成函數和一個遍歷方法:
* keys():返回鍵名的遍歷器。
* values():返回鍵值的遍歷器。
* entries():返回所有成員的遍歷器。
* forEach():遍歷Map的所有成員。
#### WeakMap
> WeakMap結構與Map結構基本類似,唯一的區別是它只接受對象作為鍵名(null除外),不接受其他類型的值作為鍵名,而且鍵名所指向的對象,不計入垃圾回收機制。