1. 程式人生 > 其它 >ES6 中的新資料結構 Set & Map 詳解

ES6 中的新資料結構 Set & Map 詳解

ES6 之 Set、Map:

  • Set 資料結構
  • Map 資料結構
  • WeakSet 和 WeakMap

1. 理解 Set 和 Map

  • Set 相當於是一種叫集合的資料結構,集合的元素都是唯一的,即 Set 資料中的元素是不重複出現的。
  • Map 相當於是一種叫字典的資料結構,字典裡的元素也是不重複的,即 Map 中的元素是不重複出現的。Map 和 Set 的不同在於 Map 是鍵值對形式出現的。
  • 共同點:集合、字典都可以儲存不重複的值
  • 不同點:集合是以[值,值]的形式儲存元素,字典是以[鍵,值]的形式儲存

2.ES6中的Set

1. Set 是一個建構函式,可以用來 new 一個例項。

let set = new Set()
set = [1,2,"red"]

2. Set 的常規方法:

  • add() 增,返回增後 Set 結構本身
  • delete() 刪,返回布林值,表示刪除是否成功
  • has() 查,返回布林值,判斷該元素是否為 Set 成員
  • clear() 清除,無返回值,清除所有成員
  • size() 返回資料長度
let set = new Set()
set.add(1).add(2).add(3).add(3)

console.log(set) //Set(3) { 1, 2, 3 }
console.log(set.size) //3

set.delete(3)
console.log(set) //Set(2) { 1, 2 }

console.log(set.has(1)) //true

set.clear()
console.log(set) //Set(0) {}

3. Set 的遍歷方法:

  • keys() : 返回鍵名
  • values() : 返回鍵值
  • entries() : 返回鍵值對
  • forEach() : 遍歷每個成員,可傳入回撥函式,該回調函式有三個引數
let set = new Set(['red', 'green', 'blue'])
for (let item of set.keys()) {
  console.log(item)
} //

console.log('---------------------')

for (let item of set.values()) {
  console.log(item)
} //

console.log('---------------------')

for (let item of set.entries()) {
  console.log(item)
} //

console.log('---------------------')

set.forEach(function (value, key, ownerSet) {
  console.log(value)
  console.log(key)
})

4. 將 Set 轉換成陣列(利用 Set 實現陣列去重)

let set = new Set([1,2,3,3])
console.log(set) // {1,2,3}
let [...arr] = set
comsole.log(arr) // [1,2,3]

5. WeakSet

Set在存放物件時,實際上是存放的是物件的引用,即Set也被稱之為Strong Set。如果所儲存的物件被置為null,但是Set例項仍然存在的話,物件依然無法被垃圾回收器回收,從而無法釋放記憶體。

let set = new Set();
let key={};
let key2 = {};
set.add(key);
set.add(key2);
console.log(set.size); //2

key=null;
console.log(set.size); //2,無法回收
如果想讓物件key正常釋放的話,可以使用Weak Set,此時,存放的是物件的弱引用,當物件只被Set弱引用的話,並不會阻止物件例項被回收。Weka Set同Set的用法幾乎一致。可以使用add()方法增加資料項,使用has()方法檢查Weak Set中是否包含某項,以及使用delete()方法刪除某一項。

 差異:

  • 對於Weak Set例項,若呼叫了add()方法時傳入了非物件的引數,則會丟擲錯誤。如果在has()或者delete()方法中傳入了非物件的引數則會返回false;
  • Weak Set不可迭代,因此不能用於for-of迴圈;
  • Weak Set 無法暴露出任何迭代器(例如 keys() 與 values() 方法) ,因此沒有任何程式設計手段可用於判斷 Weak Set 的內容;
  • Weak Set沒有forEach()方法;
  • Weak Set沒有size屬性;

3. ES6中的Map

ES6中提供了Map資料結構,能夠存放鍵值對,其中,鍵的去重是通過Object.is()方法進行比較,鍵的資料型別可以是基本型別資料也可以是物件,而值也可以是任意型別資料。

Map 的方法:

  • set() : 新增鍵值對
  • get() : 獲取值
  • has() : 查
  • delete :刪
  • clear() : 清

1.  使用set()方法可以給 Map 新增鍵值對

 let map = new Map();
 map.set('title','hello world');// 一個鍵值對
 map.set('year','2022');// 一個鍵值對
 
 console.log(map.size); //通過set()方法往Map中增加了兩個鍵值對後,可以看到Map的大小就為2;

 2. 通過get()方法可以從 Map 中提取值

 let map = new Map();
 map.set('title','hello world');
 map.set('year','2022');
 
 console.log(map.get('title')); // hello world

 3.  has(),delete()以及clear()方法

let map = new Map();
map.set('title','hello world');
map.set('year','2022');

console.log(map.has('year')); //true
map.delete('title');
console.log(map.has('title')); //false
map.clear();
console.log(map.size); //0

 4. Map 的初始化

//使用陣列來建立Map
let map = new Map([['title','hello world'],['year','2022']]);
console.log(map.has('title')); //true
console.log(map.has('year')); //true
console.log(map.size); //2

5. Map 的 forEach 方法 

與 Set 一樣,Map也擁有forEach方法,該方法也接收一個回撥函式,該回調函式有三個引數:

  1. 鍵值對的鍵;

  2. 鍵值對的值;

  3. 當前Map物件引用;

 let map = new Map([['title','hello world'],['year','2022']]);
 map.forEach((value,key,ownerMap)=>{
     console.log(value);
     console.log(key);
 });
 
 hello world
 title
 2022
 year

6. WeakMap

Weak Map對Map而言,就像是Weak Set相對於Set一樣:Weak Map(或者Weak Set)都是儲存物件弱引用的方式,在Weak Map(或者Weak Set)中,所有的鍵都必須是物件(嘗試使用非物件的鍵會丟擲錯誤),而且這些物件都是弱引用,不會干擾到垃圾回收。當Weak Map中的鍵在Weak Map之外不存在引用時,該鍵值對會被移除。
  1. Weak Map的初始化

Weak Map的鍵必須是物件,值可以是任意型別,初始化同Map一樣,也可是使用陣列來建立一個 Weak Map :

//使用陣列來建立一個Weak Map
let key = {};
let key2 = {};
let map = new WeakMap([[key,'hello'],[key2,'world']]);
console.log(map.get(key)); //hello
console.log(map.get(key2)); //world
  1. has方法以及delete方法

與Map一樣,可以使用has()方法來檢查Weak Map中是否存在某一個鍵值對,使用delete()方法可以刪除一個鍵值對。clear() 方法不存在,這是因為沒必要對鍵進行列舉,並且列舉 Weak Map 也是不可能的,這與 Weak Set 相同:

let key = {};
let key2 = {};
let map = new WeakMap([[key,'hello'],[key2,'world']]);

map.delete(key);
console.log(map.has(key)); //false

Weak Map 的用法與侷限性

當決定是要使用 Weak Map 還是使用正規 Map 時,首要考慮因素在於你是否只想使用物件型別的鍵。如果你打算這麼做,那麼最好的選擇就是 Weak Map 。因為它能確保額外資料在不再可用後被銷燬,從而能優化記憶體使用並規避記憶體洩漏。

要記住 Weak Map 只為它們的內容提供了很小的可見度,因此你不能使用 forEach() 方法、size 屬性或 clear() 方法來管理其中的項。如果你確實需要一些檢測功能,那麼正規 Map會是更好的選擇,只是一定要確保留意記憶體的使用。

4.總結

  • Set 是無重複值的有序列表。根據 Object.is()方法來判斷其中的值不相等,以保證無重複。 Set 會自動移除重複的值,因此你可以使用它來過濾陣列中的重複值並返回結果。 Set並不是陣列的子型別,所以你無法隨機訪問其中的值。但你可以使用has() 方法來判斷某個值是否存在於 Set 中,或通過 size 屬性來檢視其中有多少個值。 Set 型別還擁有forEach()方法,用於處理每個值。

  • Weak Set 是隻能包含物件的特殊 Set 。其中的物件使用弱引用來儲存,意味著當 Weak Set中的項是某個物件的僅存引用時,它不會遮蔽垃圾回收。由於記憶體管理的複雜性, Weak Set的內容不能被檢查,因此最好將 Weak Set 僅用於追蹤需要被歸組在一起的物件。

  • Map 是有序的鍵值對,其中的鍵允許是任何型別。與 Set 相似,通過呼叫 Object.is()方法來判斷重複的鍵,這意味著能將數值 5 與字串 "5" 作為兩個相對獨立的鍵。使用set() 方法能將任何型別的值關聯到某個鍵上,並且該值此後能用 get() 方法提取出來。Map 也擁有一個 size 屬性與一個 forEach() 方法,讓專案訪問更容易。

  • Weak Map 是隻能包含物件型別的鍵的特殊 Map 。與 Weak Set 相似,鍵的物件引用是弱引用,因此當它是某個物件的僅存引用時,也不會遮蔽垃圾回收。當鍵被回收之後,所關聯的值也同時從 Weak Map 中被移除。


參考文獻:
作者:你聽___
連結:https://www.jianshu.com/p/af78964c33e2
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。