ES6新的資料結構 — Set
- Set類似于數組,但其成員是唯一的,沒有重複值
<!-- 申明Set -->
var s = new Set();
var arr = [,,,,,,,,,,,,];
arr.map(i => s.add(i)); // 調用s.add()方法給Set中添加值
// 或者在聲明時,直接添加添加一個數組作為參數
var s1 = new Set(arr);
console.log(s); // Set(6) {1,3,2,4,5,6, size: 6, ...}
console.log([...s]); // [1,3,2,4,5,6]
- Set判斷值是否相等使用精确相等運算符
var s2 = new Set([,,,'2','a']);
console.log([...s2]); // [,,,'2','a']
- Set的屬性和方法:
<!-- 屬性 -->
Set.prototype.constructor: 構造函數,預設是Set()
Set.size: 傳回set執行個體的長度
<!-- 方法 -->
add(value): 添加值,傳回Set結構本身
delete(value): 删除值,傳回boolean
has(value): 判斷值是否存在,傳回boolean
clear(): 清空Set,無傳回值
- Set的周遊操作
- Set.keys()鍵名周遊器
- Set.Values()鍵值周遊器,由于Set類似于數組,沒有鍵名,是以鍵值與鍵名周遊器傳回結果一緻
- Set.entries()鍵值對周遊器
- forEach((x) => console.log(x))回調函數周遊
var s = new Set([,,,'2','a']);
for(let item of s.key()) {
console.log(item); // , , , '2' , 'a'
}
- 由于擴充運算符…的内部實作也是for…of循環,是以…同樣适用Set資料結構
有同學可能好奇WeakSet結構
- WeakSet結構與Set類似,都不能有相同的值
- 不同之處在于:
- WeakSet的成員隻能為對象,而且不能是其他的任何類型
- WeakSet對對象的引用是弱引用,及某對象在其他地方已經不使用了(WeakSet中仍舊引用該對象),系統的垃圾回收機制不會考慮WeakSet,直接回收該對象
- 由于以上兩個不同,WeakSet是不可周遊的,也沒有size屬性
- 使用WeakSet的好處是,可以防止記憶體洩漏
ES6新的資料結構 — Map
- 玩過c/c++或java等語言的童鞋都應該知道map資料結構,存取資料都很友善。ES6以前,js要從一堆鍵值對中快速的取出某個鍵值對是要經過周遊或者轉為對象的(取值也是通過周遊實作),并且對象的鍵一般隻能使用字元串,在使用上有很大的限制
- Map提供的不再是Object中的鍵值對,而是值-值對的存取
var m = new Map();
<!-- 用字元串做鍵 -->
m.set(p, 'cont');
m.get(p); // cont
m.has(p); // true
m.delete(p); // true
m.has(p); // false
<!-- 用對象 -->
var obj = {p: 'cont'};
obj.p; // cont
m.set(obj, 'hello world!');
m.get(obj); // hello world!
- Map 也接受一個儲存 值-值 對的數組作為其參數
var m = new Map([[a,'aaa'], [b, 'bbb']]);
m.get(a); // aaa
m.get(b); // bbb
- 如果對同一個鍵指派多次,後面的值覆寫前面的值
var m = new Map([[a,'aaa'], [b, 'bbb']]);
m.set(a,'ccc');
m.get(a); // ccc
- Map的鍵引用的是一個位址,而不是像對象那樣,引用的一個字元串。
<!-- 這裡先廢話幾句 -->
var quote1 = ['a'];
var quote2 = {v: 'a'};
typeof quote1; // "object"
typeof quote2; // "object"
/**
* js中的"object"類型資料是引用類型資料,一個object就會占用一塊記憶體,即使相同的值也是占用不同的記憶體
* 而其他的基礎資料類型相同的值共用同一塊記憶體
*/
<!-- 進入正題 -->
var m = new Map();
// 鍵名為基本資料類型
m.set(, 'aaa');
m.set(, 'bbb');
m.get(); // bbb
// 鍵名為引用資料類型
m.set(['a'], 'aaa');
m.get(['a']); // undefined, get的鍵 ['a'], 和 set的鍵 ['a'],指的不是同一塊記憶體,是以拿不到前面的 'aaa'
var k1 = ['a'];
var k2 = ['a'];
m.set(k1, 'aaa');
m.set(k2, 'bbb');
m.get(k1); // aaa
m.get(k2); // bbb, k1和k2指向的位址不用,存儲的值也就不同
Map的鍵為基礎資料類型時,隻要值相等,Map就會認為是同一個鍵;Map的鍵為引用資料類型時,就算長得一模一樣,但因為引用的記憶體位址不一樣,還是會被當做兩個鍵
+ Map執行個體的屬性和方法
1. size屬性,傳回map結構的成員總數
2. set(key,value)方法,設定Map的鍵值,傳回整個Map結構
3. get(key)方法,傳回key對應的鍵值
4. has(key)方法,傳回一個布爾值,表示該鍵值是否存在
5. delete(key)方法,删除key對應的鍵值,傳回一個布爾值
6. 周遊方法:keys()、values()、entries()、forEach()周遊器
var m = new Map();
m.set(,'aaa').set(,'ads').set('aaa',)
console.log(m.size); //
m.get(); // aaa
console.log(m.has()); // true
for(let key of m.keys()) {
console.log(key); // , , 'aaa'
}
for(let en of m.entries()) {
console.log(en[] + ': ' + en[]); // : 'aaa' , : 'ads' , 'aaa':
}
- Map轉數組,使用object的 … 擴充運算符
let mapToArr = [...m];
console.log(mapToArr); // [[1, "aaa"],[3, "ads"],["aaa", 231]]
- 數組轉Map:将數組傳入Map的構造函數即可
let m1 = new Map(mapToArr);
console.log(m1); // Map() { => "aaa", => "ads", "aaa" => }
- Map轉對象(前提是Map的所有鍵都是字元串)采用循環周遊Map的鍵值存儲到對象中,對象轉Map同理
WeakMap
- WeakMap與Map的結構和用法基本類似,唯一的差別在于它隻接受對象作為鍵名(null除外)
- WeakMap的鍵名是對象的弱引用,垃圾回收機制不将該引用考慮在内,當系統把對應的鍵值回收後,WeakMap自動删除該鍵值
var vm = new WeakMap();
var element = document.querySelector('.element');
vm.set(element, "Original");
vm.get(element); // Original
element.parentNode.removeChild(element); // 删除節點,系統會回收element這個Dom節點對象
element = null;
vm.get(element); // undefined, WeakMap自動删除了element這個成員
- WeakMap典型應用就是用來記錄Dom節點的狀态,當DOM節點被删除回收時,WeakMap會自動删除該DOM節點對應的成員,釋放記憶體
- WeakMap的另一個應用就是部署内部私有屬性,即鍵值引用另一個對象内的每個鍵或值或鍵值對,當該對象被删除,這個引用會被自動釋放