Map
是一个含有数据的键的集合,跟普通的 Object
一样。但是它们最大的差别是Map
允许键是任何类型。
关于Map
的方法和属性如下:
- new Map() 创建一个空集合
- map.set(key, value) 存储含有值的键
- map.get(key) 根据键来返回值,如果
key
不在map
里将会返回undefined
- map.has(key) 如果
key
存在则返回true
,否则返回false
- map.delete(key) 根据键来删除值
- map.clear 清空集合
- map.size 返回当前全部元素的数量
举个例子:
let map = new Map();
map.set('1', 'str1');
map.set(1, 'num1');
map.set(true, 'bool1');
//Map 会保持类型,而不会像Object将键转化为字符串
alert( map.get(1) ); // 'num1'
alert( map.get('1') ); // 'str1'
Map 还可以使用对象作为键
示例:
let john = { name: 'John' };
//创建一个集合可以存储每个游客的来访次数
let visitsCountMap = new Map();
// john 的来访次数是123
visitsCountMap.set(john, 123);
//读取 john 的来访次数
alert( visitsCountMap.get(john) ); // 123
使用对象作为键是 Map
最出名也是最重要的特点。
Map 是怎么比较键的?
为了测试键的一致性,Map
使用 SameValueZero 算法。它大致上使用严格相等 ===,但不同的是 NaN 被看成是等于 NaN。所以 NaN 也可以被用作键。(这个算法不能被改变或者自定义)
链式调用
每一次调用 map.set
都会返回集合本身,所以我们可以使用:
map.set('1', 'str1').set(1, 'num1').set(true, 'bool1');
Map 迭代
如果要在 map
里使用循环,可以使用以下三个方法:
- map.keys() 返回所有键的迭代器
- map.values() 返回所有值的迭代器
- map.entries() 返回包含所有键值对的迭代器,在 for..of 循环中默认被使用
示例:
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
//迭代键
for (let vegetable of recipeMap.keys()) {
alert(vegetable); // cucumber, tomatoes, onion
}
//迭代值
for (let amount of recipeMap.values()) {
alert(amount); // 500, 350, 50
}
//迭代键值对
for (let entry of recipeMap) { // 效果跟 recipeMap.entries() 相同
alert(entry); // 依次是 cucumber,500 tomatoes,350 onion,50
}
按顺序插入
迭代的顺序与插入键的顺序相同。Map
会保持相同的顺序,不像普通 Object
不保证顺序。
除此之外,Map
有个内建 forEach
方法,跟 Array
一样:
//对每个 (key, value) 对运行 forEach 函数
recipeMap.forEach( (value, key, map) => {
alert(`${key}: ${value}`); // cucumber: 500
})
Object.entries: 把对象转化为 map
当 Map
被创建之后,我们可以传入带有键值对的数组(或其它可迭代的对象)来进行初始化,像这样:
//包含 [key, value] 对的数组
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, 'bool1']
]);
alert( map.get('1') );
如果我们有个纯对象,并且想利用这个纯对象来创建 Map
,可以使用内建方法 Object.entries(obj),它返回一个具有相同格式的并且带有键值对的数组对象。
示例:
let obj = {
name: 'John',
age: 30
};
let map = new Map(Object.entries(obj));
alert( map.get('name') ); // John
这里,Object.entries 返回一个含有键值对的数组:[ ['name','John'], ['age', 30] ]。这就是 Map
所需要的参数格式。
Object.fromEntries: 把 map 转化为对象
我们刚刚已经利用 Object.entries(obj) 把一个纯对象转化成 Map
Object.fromEntries 方法的作用是相反的:给定一个具有 [key, value] 对的数组,它会根据给定数组转化为 Object
:
let prices = Object.fromEntries([
['banana', 1],
['orange', 2],
['meat', 3]
]);
alert(prices.orange); // 2
我们可以使用 Object.fromEntries 从 Map 中得到一个纯对象。
例如:我们存了数据在 Map 中,但是我们需要把它转给需要纯对象的第三方代码。
示例:
let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 3);
let obj = Object.fromEntries(map.entries());
alert(obj.orange); // 2
调用 map.entries() 将返回含有键值对的数组,这刚好是 Object.fromEntries 所需要的格式。
当然,使用下面的方式也是可以的:
let obj = Object.fromEntries(map);
上面的代码作用是一样的,因为 Object.fromEntries 需要一个可迭代对象作为参数,map 的标准迭代会返回跟 map.entries() 一样的键值对。