ES6新特性:Javascript中的Map和WeakMap物件
Map物件
Map物件是一種有對應 鍵/值 對的物件, JS的Object也是 鍵/值 對的物件 ;
ES6中Map相對於Object物件有幾個區別:
1:Object物件有原型, 也就是說他有預設的key值在物件上面, 除非我們使用Object.create(null)建立一個沒有原型的物件;
2:在Object物件中, 只能把String和Symbol作為key值, 但是在Map中,key值可以是任何基本型別(String, Number, Boolean, undefined, NaN....),或者物件(Map, Set, Object, Function , Symbol , null....);
3:通過Map中的size屬性
Map例項物件的key值可以為一個數組或者一個物件,或者一個函式,比較隨意 ,而且Map物件例項中資料的排序是根據使用者push的順序進行排序的, 而Object例項中key,value的順序就是有些規律了, (他們會先排數字開頭的key值,然後才是字串開頭的key值);
Map例項的屬性
map.size這個屬性和陣列的length是一個意思,表示當前例項的長度;
Map例項的方法
clear()方法, 刪除所有的鍵/值對;
delete(key), 刪除指定的鍵/值對;
entries()
forEach(callback , context) 迴圈執行函式並把鍵/值對作為引數; context為執行函式的上下文this;
get(key) 返回Map物件key相對應的value值;
has(key) 返回布林值, 其實就是返回Map物件是否有指定的key;
keys() 返回一個迭代器,迭代器按照插入的順序返回每一個key元素;
set(key, value) 給Map物件設定key/value 鍵/值對, 返回這個Map物件(相對於Javascript的Set,Set物件新增元素的方法叫做add,而Map物件新增元素的方法為set;
[@@iterator]
自己模擬一個Map構造器:
既然知道了Map物件的方法和屬性, 我們也可以自己模擬一個Map構造器, 需要生成器的支援, 所以要在ES5中使用還需要生成器的補丁(模擬Set構造器) :
<html> <head> <meta charMap="utf-8"> </head> <body> <script> "use strict"; class Map { /** * @param [[key, value], [k, val]]; * @return void; */ static refresh (arg) { for(let [key,value] of arg) { //判斷是否重複了; let index = Map.has.call(this, key); if(index===false) { this._keys.push(key); this._values.push(value); }else{ //如果有重複的值,那麼我們執行覆蓋; this._keys[index] = key; this._values[index] = value; } }; this.size = this._keys.length; } /** * @desc return false || Number; * */ static has (key) { var index = this._keys.indexOf(key); if(index === -1) { return false; }else{ return index; }; } constructor(arg) { this._keys = []; this._values = []; Map.refresh.call(this, arg); } set (key, value) { Map.refresh.call(this, [[key,value]]); return this; } clear () { this._keys = []; this._values = []; return this; } delete (key) { var index = Map.has.call(this, key); if(index!==false) { this._keys.splice(index,1); this._values.splice(index,1); }; return this; } entries () { return this[Symbol.iterator](); } has (key) { return Map.has.call(this, key) === false ? false : true; } *keys() { for(let k of this._keys) { yield k; } } *values () { for(let v of this._values) { yield v; } } //直接使用陣列的forEach方便啊; forEach (fn, context) { return this; } //必須支援生成器的寫法; *[Symbol.iterator] (){ for(var i=0; i<this._keys.length; i++) { yield [this._keys[i], this._values[i]]; } } }; var map = new Map([["key","value"]]); map.set("heeh","dada"); console.log(map.has("key")); //輸出:true; map.delete("key"); console.log(map.has("key")); //輸出:false; map.set("key","value"); var keys = map.keys(); var values = map.values(); console.log(keys.next()); console.log(keys.next()); console.log(values.next()); console.log(values.next()); var entries = map.entries(); console.log(entries); </script> </body> </html>View Code
Map的使用Demo:
var myMap = new Map(); var keyString = "a string", keyObj = {}, keyFunc = function () {}; // 我們給myMap設定值 myMap.set(keyString, "字串'"); myMap.set(keyObj, "物件"); myMap.set(keyFunc, "函式"); myMap.size; // 輸出長度: 3 // 獲取值 console.log(myMap.get(keyString)); // 輸出:字串 console.log(myMap.get(keyObj)); // 輸出:物件 console.log(myMap.get(keyFunc)); // 輸出:函式 console.log(myMap.get("a string")); // 輸出:字串 console.log(myMap.get({})); // 輸出:undefined console.log(myMap.get(function() {})) // 輸出:undefined
我們也可以把NaN,undefined, 物件,陣列,函式等這些作為一個Map物件的key值 :
"use strict"; let map = new Map(); map.set(undefined, "0"); map.set(NaN, {}); console.log(map); //輸出:Map { undefined => '0', NaN => {} }
迴圈Map的方法
使用Map例項的forEach方法;
"use strict"; let map = new Map(); map.set(undefined, "0"); map.set(NaN, {}); map.forEach(function(value ,key ,map) { console.log(key,value, map); });
使用for...of迴圈:
"use strict"; let map = new Map(); map.set(undefined, "0"); map.set(NaN, {}); for(let [key, value] of map) { console.log(key, value); } for(let arr of map) { console.log(arr); }
WeakMap
WeakMap是弱引用的Map物件, 如果物件在js執行環境中不存在引用的話,相對應的WeakMap物件內的該物件也會被js執行環境回收;
WeakMap物件的屬性:無
WeakMap物件的方法:
delete(key) : 刪除指定的鍵/值對;
get(key) :返回Map物件key相對應的value值;
has(key) :返回布林值, 其實就是返回Map物件是否有指定的key;
set(key):給Map物件設定key/value 鍵/值對, 返回這個Map物件;
WeakMap相對於Map少了很多的方法, 我們也可以自己再來實現這些方法,比如我們再實現一個Map例項的clear方法:
class ClearableWeakMap { constructor(init) { this._wm = new WeakMap(init) } clear() { this._wm = new WeakMap() } delete(k) { return this._wm.delete(k) } get(k) { return this._wm.get(k) } has(k) { return this._wm.has(k) } set(k, v) { this._wm.set(k, v) return this } }