ES6裏除了增長了Set(集合類型)外(筆者在這篇文章《Set與WeakSet》有過介紹),今天這篇文章將介紹引入的新類型——Map(映射類型)及WeakMap。映射類型在計算機科學中定義屬於關聯數組,而關聯數組的定義是若干鍵值對(Key/Value Pair)組成的集合,其中每一個Key值都只能出現一次。javascript
本篇文章將從如下方面進行介紹:前端
本篇文章閱讀時間預計5分鐘java
Map的鍵和值能夠是任何數據類型,鍵值對按照插入順序排列,若是插入重複的鍵值,後面的鍵值會覆蓋前者,下段代碼是個簡單示例,演示了Map的一些用法:數組
let map = new Map();
let o = {n: 1};
map.set(o, "A"); //add
map.set("2", 9);
console.log(map.has("2")); //check if key exists
console.log(map.get(o)); //retrieve value associated with key
console.log(...map);
console.log(map);
map.delete("2"); //delete key and associated value
map.clear(); //delete everything
//create a map from iterable object
let map_1 = new Map([[1, 2], [4, 5]]);
console.log(map_1.size); //number of keys複製代碼
上述代碼將會輸出bash
true
A
[ { n: 1 }, 'A' ] [ '2', 9 ]
Map { { n: 1 } => 'A', '2' => 9 }
2複製代碼
從上述代碼中,咱們能夠看出使用new Map()語法進行聲明,map鍵的類型可使用任意對象做爲鍵(字符串,object類型,functions),咱們直接二維數組鍵值對的形傳入到構建函數中,第一項爲鍵,後一項爲值。微信
const map=new Map([['foo',1],['foo',2]])
console.log(map);
console.log(map.get('foo'))複製代碼
上述代碼將會輸出:函數
Map { 'foo' => 2 }
2複製代碼
上述代碼咱們能夠看出,若是存在相同的鍵,則會按照FIFO(First in First Out,先進先出)原則,後面的鍵值信息會覆蓋前面的鍵值信息。post
如下表格羅列了Map相關的方法ui
操做方法this |
內容描述 |
---|---|
map.set(key,value) |
添加鍵值對到映射中 |
map.get(key) |
獲取映射中某一個鍵的對應值 |
map.delete(key) |
將某一鍵值對移除映射 |
map.clear() |
清空映射中全部鍵值對 |
map.entries() |
返回一個以二元數組(鍵值對)做爲元素的數組 |
map.has(key) |
檢查映射中是否包含某一鍵值對 |
map.keys() |
返回一個當前映射中全部鍵做爲元素的可迭代對象 |
map.values() |
返回一個當前映射中全部值做爲元素的可迭代對象 |
map.size |
映射中鍵值對的數量 |
let user={name:"Aaron",id:1234};
let userHobbyMap=new Map();
userHobbyMap.set(user,['Ice fishing','Family Outting']);//添加鍵值對
console.log(userHobbyMap);
userHobbyMap.delete(user);//刪除鍵值對
userHobbyMap.clear(); //清空鍵值對
console.log(userHobbyMap);複製代碼
上述代碼將會輸出:
Map { { name: 'Aaron', id: 1234 } => [ 'Ice fishing', 'Family Outting' ] }
Map {}複製代碼
與Set集合對象不同,集合對象的元素沒有元素位置的標識,故沒有辦法獲取集合某元素,可是映射對象由鍵值對組成,因此能夠利用鍵來獲取對應的值。
const map=new Map();
map.set('foo', 'bar');
console.log(map.get('foo')); //output bar複製代碼
與Set集合同樣,Map映射也可使用has(鍵)的方法來檢查是否包含某鍵。
const map=new Map([['foo',1]])
console.log(map.has('foo'));//output true
console.log(map.has('bar'));//output false複製代碼
映射對象在設計上一樣也是一種可迭代的對象,能夠經過for-of循環對其遍歷,同時也可使用foreach進行遍歷。 映射對象中帶有entries()方法,用於返回包含全部鍵值對的可迭代的二元數組對象,而for-of和foreach即是先利用entries()方法先將映射對象轉換成一個類數組對象,然年再進行迭代。
const map=new Map([['foo',1],['bar',2]]);
console.log(Array.from(map.entries()));
//output
//[ [ 'foo', 1 ], [ 'bar', 2 ] ]
for(const [key,value] of map){
console.log(`${key}:${value}`);
}
//output
//foo:1
//bar:2
map.forEach((value,key,map)=>
console.log(`${key}:${value}`))
//output
//foo:1
//bar:2複製代碼
說了這麼多映射對象的方法,Map和Object對象有哪些區別呢,如下表格進行了總結:
對比項 |
映射對象Map |
Object對象 |
---|---|---|
存儲鍵值對 |
√ |
√ |
遍歷全部的鍵值對 |
√ |
√ |
檢查是否包含指定的鍵值對 |
√ |
√ |
使用字符串做爲鍵 |
√ |
√ |
使用Symbol做爲鍵 |
√ |
√ |
使用任意對象做爲鍵 |
√ |
|
能夠很方便的得知鍵值對的數量 |
√ |
|
從中咱們能夠看出Map對象可使用任何對象做爲鍵,這就解決了咱們實際應用中一個很大的痛點,好比如今一個DOM對象做爲鍵時,Object就不是那麼好用了。
與集合類型(Set)同樣,映射類型也有一個Weak版本的WeakMap。WeakMap和WeakSet很類似,只不過WeakMap的鍵會檢查變量的引用,只要其中任意一個引用被釋放,該鍵值對就會被刪除。
如下三點是Map和WeakMap的主要區別: 1.Map對象的鍵能夠是任何類型,但WeakMap對象中的鍵只能是對象引用 2.WeakMap不能包含無引用的對象,不然會被自動清除出集合(垃圾回收機制)。 3.WeakSet對象是不可枚舉的,沒法獲取大小。
下段代碼示例驗證了WeakMap的以上特性:
let weakmap = new WeakMap();
(function(){
let o = {n: 1};
weakmap.set(o, "A");
})(); // here 'o' key is garbage collected
let s = {m: 1};
weakmap.set(s, "B");
console.log(weakmap.get(s));
console.log(...weakmap); // exception thrown
weakmap.delete(s);
weakmap.clear(); // Exception, no such function
let weakmap_1 = new WeakMap([[{}, 2], [{}, 5]]); //this works
console.log(weakmap_1.size); //undefined」複製代碼
const weakmap=new WeakMap();
let keyObject={id:1};
const valObject={score:100};
weakmap.set(keyObject, valObject);
console.log(weakmap.get(keyObject));
//output { score: 100 }
keyObject=null;
console.log(weakmap.has(keyObject));
//output false複製代碼
今天的內容就介紹到這裏,咱們明白了Map是一個鍵值對的映射對象,相比Object來講可使用任何鍵作爲鍵值,而且可以很方便的獲取鍵值對。WeakMap相對於Map是一個不可枚舉的對象,必須使用對象做爲鍵值。如何更好的使用Map和WeakMap還須要具體結合咱們實際的業務場景進行靈活使用。