es6-認識Set和Map

在es5中常常用對象來實現集合set 和映射 map 的數據結構,可是這種方式有一些弊端。好比實現集合時,咱們不能用 if(set.count) 判斷某個元素是否確切存在。在集合中,屬性5和'5'會被看成同一個鍵,還有不能使用對象做爲鍵,由於會轉爲[object object]。因此,es6提供了兩種新的數據解構:Set 集合和Map 映射。git

Set集合

經過 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
複製代碼

Map映射

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 }
複製代碼

MapSet同樣擁有 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和WeakMap

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
複製代碼

WeakSetWeakMap 不支持 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
複製代碼

參考

ES6 系列之 WeakMap

>>>原文地址

相關文章
相關標籤/搜索