ES6 Map 的用法与实战

963 阅读1分钟

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?为什么?

参考文献