《深刻理解ES6》筆記——Set集合與Map集合(7)

Map和Set都叫作集合,可是他們也有所不一樣。Set常被用來檢查對象中是否存在某個鍵名,Map集合常被用來獲取已存的信息。面試

Set

Set是有序列表,含有相互獨立的非重複值。

建立Set

既然咱們如今不知道Set長什麼樣,有什麼價值,那麼何不建立一個Set集合看看呢?編程

建立一個Set集合,你能夠這樣作:segmentfault

let set = new Set();
console.log(set);

//在瀏覽器控制檯的輸出結果
Set(0) {}
    size:(...)
    __proto__:Set
    [[Entries]]:Array(0)
    length:0

看起來像個對象,那麼如今咱們在控制檯打印一個對象,對比一下二者有什麼不一樣。數組

let obj = new Object()
console.log(obj)

//在控制檯輸出對象
Object {}
    __proto__:

從輸出結果看,Set和Object有明顯的區別,反正他們就不是一個東西。瀏覽器

接着,咱們看一下Set的原型有哪些:學習

clipboard.png

這裏主要介紹幾個基礎原型的做用,想要了解所有請前往 Set集合之家 查看:測試

Set.prototype.size
返回Set對象的值的個數。this

Set.prototype.add(value)
在Set對象尾部添加一個元素。返回該Set對象。spa

Set.prototype.entries()
返回一個新的迭代器對象,該對象包含Set對象中的按插入順序排列的全部元素的值的[value, value]數組。爲了使這個方法和Map對象保持類似, 每一個值的鍵和值相等。prototype

Set.prototype.forEach(callbackFn[, thisArg])
按照插入順序,爲Set對象中的每個值調用一次callBackFn。若是提供了thisArg參數,回調中的this會是這個參數。

Set.prototype.has(value)
返回一個布爾值,表示該值在Set中存在與否。

在例子中使用這幾個方法測試一下:

let set = new Set();
set.add('haha');
set.add(Symbol('haha'));

console.log(set.size); //2

console.log(set); 
Set(2) {"haha", Symbol(haha)}
    size:(...)
    __proto__:Set
    [[Entries]]:Array(2)
        0:"haha"
        1:Symbol(haha)
    length:2
    
console.log(set.has('haha')) // true

到這裏,你會發現Set像數組,又像一個對象,但又不徹底是。

迭代Set

Set既然提供了entries和forEach方法,那麼他就是可迭代的。

但若是你使用for in來迭代Set,你不能這樣作:

for(let i in sets) {
  console.log(i); //不存在
}

for in迭代的是對象的key,而在Set中的元素沒有key,使用for of來遍歷

for(let value of sets) {
  console.log(value);
}
//"haha"
//Symbol(haha)

//若是你須要key,則使用下面這種方法
for(let [key, value] of sets.entries()) {
  console.log(value, key);
} 
//"haha" "haha"
//Symbol(haha) Symbol(haha)

forEach操做Set:Set自己沒有key,而forEach方法中的key被設置成了元素自己。

sets.forEach((value, key) => {
  console.log(value, key);
});
//"haha" "haha"
//Symbol(haha) Symbol(haha)

sets.forEach((value, key) => {
  console.log(Object.is(value, key));
}); 
//true true

Set和Array的轉換

Set和數組太像了,Set集合的特色是沒有key,沒有下標,只有size和原型以及一個可迭代的不重複元素的類數組。既然這樣,咱們就能夠把一個Set集合轉換成數組,也能夠把數組轉換成Set。

//數組轉換成Set
const arr = [1, 2, 2, '3', '3']
let set = new Set(arr);
console.log(set) // Set(3) {1, 2, "3"}

//Set轉換成數組
let set = new Set();
set.add(1);
set.add('2');
console.log(Array.from(set)) // (2) [1, "2"]

js面試中,常常會考的一道數組去重題目,就可使用Set集合的不可重複性來處理。經測試只能去重下面3種類型的數據。

const arr = [1, 1, 'haha', 'haha', null, null]
let set = new Set(arr);
console.log(Array.from(set)) // [1, 'haha', null]
console.log([...set]) // [1, 'haha', null]

Weak Set集合

Set集合自己是強引用,只要new Set()實例化的引用存在,就不釋放內存,這樣一刀切確定很差啊,好比你定義了一個DOM元素的Set集合,而後在某個js中引用了該實例,可是當頁面關閉或者跳轉時,你但願該引用應當即釋放內存,Set不聽話,那好,你還可使用 Weak Set

語法:

new WeakSet([iterable]);

和Set的區別:

一、WeakSet 對象中只能存放對象值, 不能存放原始值, 而 Set 對象均可以.

二、WeakSet 對象中存儲的對象值都是被弱引用的, 若是沒有其餘的變量或屬性引用這個對象值, 則這個對象值會被當成垃圾回收掉. 正由於這樣, WeakSet 對象是沒法被枚舉的, 沒有辦法拿到它包含的全部元素.

使用:

let set = new WeakSet();
const class_1 = {}, class_2 = {};
set.add(class_1);
set.add(class_2);
console.log(set) // WeakSet {Object {}, Object {}}
console.log(set.has(class_1)) // true
console.log(set.has(class_2)) // true

Map

Map是存儲許多鍵值對的有序列表,key和value支持全部數據類型。

建立Map

若是說Set像數組,那麼Map更像對象。而對象中的key只支持字符串,Map更增強大,支持全部數據類型,不論是數字、字符串、Symbol等。

// 一個空Map集合
let map = new Map()
console.log(map)

clipboard.png

Map的全部原型方法:
clipboard.png

對比Set集合的原型,Map集合的原型多了set()和get()方法,注意set()和Set集合不是一個東西。Map沒有add,使用set()添加key,value,在Set集合中,使用add()添加value,沒有key。

let map = new Map();
map.set('name', 'haha');
map.set('id', 10);
console.log(map)
// 輸出結果
Map(2) {"name" => "haha", "id" => 10}
    size:(...)
    __proto__:Map
    [[Entries]]:Array(2)
        0:{"name" => "haha"}
        1:{"id" => 10}
    length:2

console.log(map.get('id')) // 10
console.log(map.get('name')) // "haha"

使用對象作key

let map = new Map();
const key = {};
map.set(key, '誰知道這是個什麼玩意');
console.log(map.get(key)) // 誰知道這是個什麼玩意

Map一樣可使用forEach遍歷key、value

let map = new Map();
const key = {};
map.set(key, '這是個什麼玩意');
map.set('name', 'haha');
map.set('id', 1);
map.forEach((value, key) => {
  console.log(key, value)
})

//Object {} "這是個什麼玩意"
//"name" "haha"
//"id" 1

其餘Map的使用方法能夠前往 Map之家 學習。

Weak Map

有強Map,就有弱雞Map。

和Set要解決的問題同樣,但願再也不引用Map的時候自動觸發垃圾回收機制。那麼,你就須要Weak Map。

let map = new WeakMap();
const key = document.querySelector('.header');
map.set(key, '這是個什麼玩意');

map.get(key) // "這是個什麼玩意"

//移除該元素
key.parentNode.removeChild(key);
key = null;

總結

Set集合能夠用來過濾數組中重複的元素,只能經過has方法檢測指定的值是否存在,或者是經過forEach處理每一個值。

Weak Set集合存放對象的弱引用,當該對象的其餘強引用被清除時,集合中的弱引用也會自動被垃圾回收機制回收,追蹤成組的對象是該集合最好的使用方式。

Map集合經過set()添加鍵值對,經過get()獲取鍵值,各類方法的使用查看文章教程,你能夠把它當作是比Object更增強大的對象。

Weak Map集合只支持對象類型的key,全部key都是弱引用,當該對象的其餘強引用被清除時,集合中的弱引用也會自動被垃圾回收機制回收,爲那些實際使用與生命週期管理分離的對象添加額外信息是很是適合的使用方式。

記得剛開始學習JavaScript的時候,不知道各類數據類型有什麼用,若是你如今剛學習Map和Set也是這種不知道能用來幹什麼的想法,那麼,恭喜,他們已經開始走入你的編程生涯,慢慢的你就會熟悉他們。

=> 返回文章列表

相關文章
相關標籤/搜索