在es5中常常用對象來實現集合set
和映射 map
的數據結構,可是這種方式有一些弊端。好比實現集合時,咱們不能用 if(set.count)
判斷某個元素是否確切存在。在集合中,屬性5和'5'會被看成同一個鍵,還有不能使用對象做爲鍵,由於會轉爲[object object]
。因此,es6提供了兩種新的數據解構:Set
集合和Map
映射。git
經過 new Set()
建立一個空的集合,經過 add()
方法往集合添加元素:es6
let set = new Set();
set.add(5);
set.add('5');
console.log(set); // Set { 5, '5' }
複製代碼
添加進集合的元素會自動去重,而且內部使用 Object.is()
方法來判斷兩個元素是否相等,可是+0和-0除外,他們在集合中被視爲相等:github
let set = new Set();
set.add(5);
set.add('5');
set.add(5);
console.log(set.size); // 2
複製代碼
集合可用具備迭代器接口的數據進行初始化,好比用一個數組:數組
let set = new Set([1, 2, 2, 3, 4, 5, 5]);
console.log(set); // Set { 1, 2, 3, 4, 5 }
複製代碼
另一些集合的方法:數據結構
has(key)
: 判斷某個值是否存在delete(key)
: 移除集合某一個元素clear()
: 清除集合的全部元素let set = new Set();
set.add(5);
set.add('5');
console.log(set.has(5)); // true
set.delete(5);
console.log(set.has(5)); // false
console.log(set.size); // 1
set.clear();
console.log(set.size); // 0
複製代碼
相似數組,集合Set
也有 forEach
方法,第一個參數爲循環的函數,第二個參數爲綁定這個函數的 this
對象。對於循環函數的參數,第一個和第二個都爲集合每一個循環元素:函數
let set = new Set([1, 2]);
set.forEach((value, key, own) => {
console.log(key + ' ' + value);
console.log(own === set);
});
// 1 1
// true
// 2 2
// true
複製代碼
用 new Map()
新建一個空的映射,經過 set()
方法添加鍵值對,get()
方法獲取對應鍵的值:post
let map = new Map();
map.set('title', 'ECMA 2016');
map.set('year', 2016);
console.log(map.get('title')); // ECMA 2016
console.log(map.get('year')); // 2016
複製代碼
在 Map
集合中,容許對象做爲鍵:ui
let map = new Map();
let key1 = {},
key2 = {};
map.set(key1, 4).set(key2, 34);
console.log(map); // Map { {} => 4, {} => 34 }
console.log(map.get(key1)); // 4
複製代碼
能夠向 Map
構造函數傳一個數組來初始化。數組的子元素是包含鍵和值兩個元素的數組:this
let map = new Map([['name', 'wozien'], ['age', 25]]);
console.log(map); // Map { 'name' => 'wozien', 'age' => 25 }
複製代碼
Map
和 Set
同樣擁有 has(key)
, clear()
, delete(key)
三個方法,而且擁有 size
屬性,表示鍵值對的個數:es5
let map = new Map();
map.set('name', 'wozien');
map.set('age', 25);
console.log(map.size); // 2
console.log(map.has('name')); // true
map.delete('name');
console.log(map.has('name')); // false
map.clear();
console.log(map.size); // 0
複製代碼
WeakSet
表示弱引用集合,什麼是弱引用,來看一個例子:
let set = new Set();
let obj = {};
set.add(obj);
console.log(set.size); // 1
obj = null;
console.log(set.size); // 1
複製代碼
上面的代碼先在集合插入一個對象,而後把這個對象的引用obj設置 null
,清除了對該對象的引用。從集合的元素個數不變能夠看出,該對象的內存並無被回收,也就是說集合set仍然引用着這個對象,也稱強引用。
相對的,若是存在一種集合,在外部的引用都不存在時,集合的對象會自動被垃圾回收,該集合就能夠稱爲對該對象的弱引用。WeakSet
的做用就是這樣:
let set = new WeakSet();
let obj = {};
set.add(obj);
console.log(set.has(obj)); // true
obj = null;
console.log(set.has(obj)); // false
複製代碼
相似的,WeakMap
叫作弱引用Map,它的鍵名必須爲一個對象,不然會報錯:
let set = new WeakMap();
let obj = {};
set.set(obj, 1);
console.log(set.has(obj)); // true
obj = null;
console.log(set.has(obj)); // false
複製代碼
WeakSet
和 WeakMap
不支持 clear()
和 forEach()
方法。由於垃圾回收執行不能預測,所謂二者都沒有 size
屬性。
let set = new WeakMap();
let obj = {};
set.set(obj, 1);
console.log(set.size); // undefined
複製代碼
利用Set
進行數組去重:
let arr = [1, 2, 2, 3, 4, 4, 5];
arr = [...new Set(arr)];
console.log(arr); // [ 1, 2, 3, 4, 5 ]
複製代碼
利用 WeakMap
記錄DOM元素的額外信息,並隨着DOM的移除自動清除:
let wm = new WeakMap(), element = document.querySelector(".element");
wm.set(element, "data");
let value = wm.get(elemet);
console.log(value); // data
element.parentNode.removeChild(element);
element = null;
複製代碼
除了Symbol
外,咱們一樣能夠利用 WeakMap
實現對象的私有屬性:
let privateData = new WeakMap();
class Person {
constructor(name) {
privateData.set(this, { name });
}
getName() {
return privateData.get(this).name;
}
}
let person = new Person('wozien');
console.log(person.getName()); // wozien
複製代碼