【ES6基礎】Set 與 WeakSet

前端達人發表於2019-04-25

【ES6基礎】Set 與 WeakSet

在開發過程中,我們會經常使用到陣列Array這種引用型別的資料結構,並十分清楚陣列是種有序的集合,並且每個元素都可以使用數字下標的形式獲取。但是在一些業務場景中,我們並不需要集合維護一個有序的狀態,甚至有些場景需要無序集合,因此ES6里加入了無序集合Set和其的Weak版本WeakSet。

其實無序集合的概念十分容易理解,我們可以認為是沒有排序概念的陣列,並且具有元素不可重複的特性。

這篇文章筆者將從以下幾方面進行介紹:

  • Set程式碼示例
  • Set和Array的區別
  • Set常用方法
  • WeakSet介紹

本篇文章閱讀時間預計5分鐘

Set程式碼示例

Set需要使用新語法new Set()宣告,程式碼如下:

let set = new Set("Hello!!!");
set.add(12); //add 12
console.log(set.has("!")); //check if value exists
console.log(set.size);
set.delete(12); //delete 12
console.log(...set);
set.clear(); //delete all values”
//output
//true
//6
//H e l o !複製程式碼

這段程式碼我們向Set集合裡新增了一個字串和數字,字串在Set集合裡會被拆分成字元進行儲存,由於Set集合去重的特點,l和!重複將會被去重( Set { 'h', 'e', 'l', 'o' ,'!'}),使用add方法新增了12到Set集合裡,因此集合的大小是6。

Set與Array的區別

以下表格為Array和Set的區別

對比項ArraySet
元素序列有序無序
元素可重複性元素可重複元素不可重複

Set常用方法

以下表格羅列了Set相關的方法

方法介紹
set.add(value)新增元素到集合內
set.delete(value)刪除元素的指定元素
set.clear()清空集合內元素
set.forEach(callbackFn,[,context])遍歷集合內所有元素,並作為CallbackFn的引數進行呼叫
set.has(value)檢查集合內是否含有某元素

新增刪除清空

const set=new Set();
set
 .add(1)
 .add(2)
 .add(3)
 .add(3);//不起作用,因為3已經在集合中
console.log(set);//output Set { 1, 2, 3 }

//刪除元素
set.delete(2);
console.log(set);//output Set {1,3}

//清空集合
set.clear();
console.log(set); //output Set{}
複製程式碼

檢查元素

因為Set集合裡沒有排序的概念,因此我們無法使用Array的IndexOf的方法判斷是否大於0來檢驗是否含有某元素,ES6裡使用了更簡潔、更易懂的方法來檢驗是否含有某元素。

const set=new Set([1,2,3,4]);
set.has(2) //output true;
set.has(5) //output false;
複製程式碼

遍歷元素

集合物件自身定義了forEach方法,跟陣列型別的foreach一樣,示例程式碼如下:

const set=new Set([1,2,3,4]);
set.forEach(item=>{
  console.log(item);
})
//output
//1
//2
//3
//4
複製程式碼

WeakSet介紹

JavaScript垃圾回收是一種記憶體管理技術。在這種技術中,不再被引用的物件會被自動刪除,而與其相關的資源也會被一同回收。Set中物件的引用都是強型別化的,並不會允許垃圾回收。這樣一來,如果Set中引用了不再需要的大型物件,如已經從DOM樹中刪除的DOM元素,那麼其回收代價是昂貴的。

為了解決這個問題,ES6還引入了WeakSet的弱集合。這些集合之所以是“弱的”,是因為它們允許從記憶體中清除不再需要的被這些集合所引用的物件。

首先讓我們瞭解下WeakSet與Set的不同,以下三點是WeakSet與Set不一樣的地方:

  1. Set可以儲存值型別和物件引用型別,而WeakSet只能儲存物件引用型別,否則會丟擲TypeError。
  2. WeakSet不能包含無引用的物件,否則會被自動清除出集合(垃圾回收機制)。
  3. WeakSet物件是不可列舉的,也就是說無法獲取大小,也無法獲取其中包含的元素。

如下段的程式碼驗證了上述特性:

let weakset = new WeakSet();
(function(){ 
   let a = {}; 
   weakset.add(1); //TypeError: Invalid value used in weak set
   weakset.add(a);
})();  //here 'a' is garbage collected from weakset
console.log()
console.log(weakset.size); //output "undefined"
console.log(...weakset); //Exception is thrown
weakset.clear(); //Exception, no such function
複製程式碼
const weakset=new WeakSet();
let foo={bar:1};
weakset.add(foo);
console.log(weakset.has(foo)); //output true
foo=null;
console.log(weakset.has(foo)); //output false
複製程式碼

小節

今天的內容就介紹到這裡,在今後的業務中,我們除了可以使用陣列Array,還可以使用Set和WeakSet。 如果不涉及排序需要去重的業務場景,我們可以嘗試使用set,如果你想優化程式記憶體的使用,你可以嘗試使用WeakSet。


相關文章