Js大部分歷史時期都只存在一種集合類型,也就是數組類型。數組在 JS 中的使用正如其餘語言的數組同樣,但缺乏更多類型的集合致使數組也常常被看成隊列與棧來使用。數組只使用了數值型的索引,而若是非數值型的索引是必要的,開發者便會使用非數組的對象。這種技巧引出了非數組對象的定製實現,即 Set 與 Map 。es6
Set對象是值的集合,你能夠按照插入的順序迭代它的元素。 Set中的元素只會出現一次,即 Set 中的元素是惟一的。編程
Set結構相似於數組,可是沒有重複結構
Set會自動移除重複的值,所以能夠用來過濾數組中的重複結構
Set內的對象是強引用
a) let set = new Set([1, 2, 3, 4]);
Set 構造器實際上能夠接收任意可迭代對象做爲參數。能使用數組是由於它們默認就是可迭代的,Set與Map也是同樣,Set構造器會使用迭代器來提取參數中的值數組
b) let set = new Set(); set.add(1); set.add(2); set.add(2); //若是add對相同的值進行了屢次調用,那麼那麼在第一次以後的調用實際上會被忽略 set.add(3); set.add('3');
Set 不會使用強制類型轉換來判斷值是否重複。這意味着 Set 能夠同時包含數值 3 與 字符串 "3" ,將它們都做爲相對獨立的項.
Set判斷是否重複使用了Object.is() 方法,惟一的例外是 +0 與 -0 在 Set 中被判斷爲是相等的數據結構
c) 還能夠向Set添加多個值相同的對象,他們不會被合併爲同一項。函數
let set = new Set(); let key1 = {}; let key2 = {}; set.add(key1); set.add(key2);
Set.prototype.constructor:構造函數,默認就是Set函數。 Set.prototype.size:返回Set實例的成員總數。
Set的方法分爲兩類:操做方法 和 遍歷方法this
•add(value):添加某個值,返回 Set 結構自己。 由於返回set自己,因此能夠寫成: set.add(1).add(2).add(3) •delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。 set.delete(2) ; // true •has(value):返回一個布爾值,表示該值是否爲Set的成員。 set.has(2) ; // false •clear():清除全部成員,沒有返回值。
es5給數組添加了forEach()方法,使得更容易處理數組中的每一項,沒有返回值
對於數組來講forEach的三個參數:
arr[].forEach(function(value,index,array){//do})
value數組中的當前項, index當前項的索引, array原始數組es5
可是對於Set來講:prototype
let set2 = new Set([{'a':1}, {'b':2}]); set2.forEach(function(value, key, ownerSet) { console.log(ownerSet === set2); console.log(value === key); }); key 與 value 老是相同的,同時 ownerSet 也始終等於 set 。此代碼輸出: true true true true
若是想在回調函數中使用當前的this,還能夠在forEach中傳入this做爲第二個參數code
let set = new Set([1, 2]); let processor = { output(value) { console.log(value); }, process(dataSet) { dataSet.forEach(function(value) { this.output(value); }, this); } }; processor.process(set);
本例中,在processor.process方法中的set調用了forEach方法,並傳遞了this做爲第二個參數,這樣便能正確的調用到this.output()方法
或者也可使用箭頭函數來達到相同的效果,無需傳入this,只需將上邊的process改寫成:對象
process(dataSet) { dataSet.forEach((value) => this.output(value)); }
keys():返回鍵名的遍歷器
values():返回鍵值的遍歷器
entries():返回鍵值對的遍歷器
keys方法、values方法、entries方法返回的都是遍歷器對象,因爲Set結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),因此keys方法和values方法的行爲徹底一致。
let set = new Set(['red', 'green', 'blue']); for (let item of set.keys()) { console.log(item); } // red // green // blue for (let item of set.values()) { console.log(item); } // red // green // blue for (let item of set.entries()) { console.log(item); } // ["red", "red"] // ["green", "green"] // ["blue", "blue"]
上面代碼中,entries方法返回的遍歷器,同時包括鍵名和鍵值,因此每次輸出一個數組,它的兩個成員徹底相等。
Set 結構的實例默承認遍歷,它的默認遍歷器生成函數就是它的values方法。
Set.prototype[Symbol.iterator] === Set.prototype.values
// true
這就意味着,能夠省略values方法,直接用for…of循環遍歷Set
let set = new Set(['red', 'green', 'blue']); for (let x of set) { console.log(x); } // red // green // blue
Set最經典的應用就是數組排重:
let set = new Set([1, 2, 3, 3, 3, 4, 5]), array = [...set]; console.log(array);
使用擴展運算符能夠很簡單的將Set轉成數組
let set = new Set([1, 2, 3, 3, 3, 4, 5]), let array = [...set]; console.log(array); // [1,2,3,4,5]
該示例很好的說明了Set的一個重要的功能,數組排重,固然也很好的展現了,如何從Set轉成數組的過程。
注意,這種轉變是生成了一個新的數組對象原來的Set依然存在。
如最初的構造示例:
let set = new Set([1,4,5,6,7]);
因爲 Set 類型存儲對象引用的方式,它也能夠被稱爲 Strong Set 。對象存儲在 Set 的一個實例中時,實際上至關於把對象存儲在變量中。只要對於 Set 實例的引用仍然存在,所存儲的對象就沒法被垃圾回收機制回收,從而沒法釋放內存。
當 JS 代碼在網頁中運行,同時你想保持與 DOM 元素的聯繫,在該元素可能被其餘腳本移除的狀況下,你應當不但願本身的代碼保留對該 DOM 元素的最後一個引用(這種狀況被稱爲內存泄漏)
爲了緩解這個問題, ES6 也包含了 Weak Set ,該類型只容許存儲對象弱引用,而不能存儲基本類型的值。對象的弱引用在它本身成爲該對象的惟一引用時,不會阻止垃圾回收。
WeakSet 裏面的引用,都不計入垃圾回收機制,因此就不存在這個問題。所以,WeakSet 適合臨時存放一組對象,以及存放跟對象綁定的信息。只要這些對象在外部消失,它在 WeakSet 裏面的引用就會自動消失
Weak Set 使用 WeakSet 構造器來建立:
let set = new WeakSet(), key = {}; // 將對象加入 set set.add(key); console.log(set.has(key)); // true set.delete(key); console.log(set.has(key)); // false
基於WeakSet的弱引用特性,且裏邊的對象有可能隨時消失的特性,es6規定WeakSet不可遍歷,且沒有size屬性,WeakSet只有如下三個方法:
WeakSet.prototype.add(value):向 WeakSet 實例添加一個新成員。
WeakSet.prototype.delete(value):清除 WeakSet 實例的指定成員。
WeakSet.prototype.has(value):返回一個布爾值,表示某個值是否在 WeakSet 實例之中。
- 對於 WeakSet 的實例,若調用add()方法時傳入了非對象的參數,就會拋出錯誤(has()或delete()則會在傳入了非對象的參數時返回false);
- Weak Set 不可迭代,所以不能被用在 for-of 循環中;
- Weak Set 沒法暴露出任何迭代器; (例如 keys()與values() 方法,所以沒有任何編程手段可用於判斷 Weak Set 的內容);
- Weak Set 沒有 forEach() 方法;
- Weak Set 沒有 size 屬性。
WeakSet之因此不可遍歷是因爲 WeakSet 內部有多少個成員,取決於垃圾回收機制有沒有運行,運行先後極可能成員個數是不同的,而垃圾回收機制什麼時候運行是不可預測的,所以 ES6 規定 WeakSet 不可遍歷。WeakSet經常使用場景Weak Set 看起來功能有限,而這對於正確管理內存而言是必要的。通常來講,若只想追蹤對象的引用,應當使用 Weak Set 而不是正規 Set