Map 和 Object 类型相似,都可以存储键值对。但 Object 的键只能是字符串,而 Map 的键可以是任意类型(甚至可以是 Object!)。
基础用法
// 创建新的 Map
const myMap = new Map();
// 设置键值对
myMap.set('answer', 42);
// 获取值
myMap.get('answer');
// => 42
// 判断键是否存在
myMap.has('answer');
// => true
myMap.has('question');
// => false
// 删除键值对。删除成功返回 true,否则返回 false
myMap.delete('question');
// => false
myMap.delete('answer');
// => true
// 获取键值对个数
myMap.size;
// => 0
// 删除所有键值对,一了百了
myMap.clear();
注意,请勿在 Map 实例上使用 map[key]。这是对 Map 的一种侮辱。只有使用 set, get 等才能发挥 Map 的实力。
Map 的遍历
Map 有三种方法,返回 iterable 对象,供 for..of 循环使用。
map.keys()返回键map.values()返回值map.entries()返回键值对[key, value],这是for..of的默认值
const heroes = new Map([
['ironman', 'Tony Stark'],
['spiderman', 'Peter Parker'],
['batman', 'Bruce Wayne'],
]);
// 此处省略了 heroes.entries(),因为它是 for..of 默认值
for (let hero of heroes) {
console.log(hero);
// => ['ironman', 'Tony Stark']
// => ['spiderman', 'Peter Parker']
// => ['batman', 'Bruce Wayne']
}
for (let nickname of heroes.keys()) {
console.log(nickname);
// => 'ironman'
// => 'spiderman'
// => 'batman'
}
for (let realname of heroes.values()) {
console.log(realname);
// => 'Tony Stark'
// => 'Peter Parker'
// => 'Bruce Wayne'
}
此外,Map 也有 forEach 方法,用法和 Array 的同名方法一样。
heroes.forEach((value, key, map) => {
console.log(`${key}: ${value}`);
});
实战
下面以一道面试题展示 Map 的实战用法。
题目:给定一个数组 arr,元素均为基本变量,请编写函数获得出现次数最多的元素。
- 如果
arr = [1, 2, 2, '1'],则返回[2]; - 如果
arr = [1, 2, 2, '3', 4, '3', null, null],则返回[2, '3', null]
解答:
function getMostItems(arr) {
// 元素和出现次数
const map = new Map();
// 最多的出现次数
let max = 0;
// 寻找最大次数
for (let item of arr) {
map.set(item, (map.get(item) || 0) + 1);
max = Math.max(map.get(item), max);
}
const result = [];
for (let [item, num] of map) {
if (num === max) {
result.push(item);
}
}
return result;
}
思考一下,这里能不能用 Object 代替 Map?为什么?