传统上,存储键值对的数据结构时,对象 (Object) 一直是我们的首选。然而,ES6 引入了 Map 对象,它提供了一种更强大、更灵活的方式来处理键值对。以前也懒得用,直到最近用了下,我发现 Map 比对象更香。
1. 键的类型不再局限
这是 Map 最显著的优势之一。对象只能使用字符串或 Symbol 作为键,这限制了其适用性。Map 则不同,可以使用任何数据类型作为键,包括对象、函数、数字,甚至 NaN。想象一下,你想要使用 DOM 元素作为键来存储与其相关的数据,Map 可以轻松实现:
对象则无法实现这种灵活的键类型。
2. 键的顺序得到保留
对象的属性在添加时,其顺序是不确定的,尤其是在较旧的 JavaScript 引擎中。虽然现代 JavaScript 引擎尝试保留属性的插入顺序,但这种行为并非总是可靠的。Map 则不同,Map 对象会按照键值对插入的顺序进行存储和迭代。这在需要维护特定顺序的场景下非常有用:
3. 轻松获取大小
要获取对象中属性的数量,你需要手动遍历或者使用 Object.keys(obj).length,这既不优雅,也可能效率不高。Map 对象提供了一个简单的 size 属性,可以直接获取键值对的数量:
4. 避免原型链污染
JavaScript 对象会继承原型链上的属性。这意味着,如果不小心,你可能会意外访问到原型链上的属性,或者更糟糕的是,修改原型链上的属性,导致全局污染。Map 对象不会继承任何属性,它完全隔离于原型链,更加安全可靠。
5. 更优的性能
在某些场景下,特别是需要频繁添加、删除键值对的情况下,Map 对象通常比对象具有更好的性能。JavaScript 引擎对 Map 对象进行了专门的优化,使其更适合处理动态数据。
6. 内置的迭代方法
Map 对象提供了内置的迭代方法,例如 forEach、keys、values 和 entries,使得迭代键值对变得非常方便:
const myMap = new Map();
myMap.set('a', 1);
myMap.set('b', 2);
myMap.forEach((value, key) => {
console.log(key, value); // 输出: a 1, b 2
});
for (const key of myMap.keys()) {
console.log(key); // 输出: a, b
}
for (const value of myMap.values()) {
console.log(value); // 输出: 1, 2
}
for (const [key, value] of myMap.entries()) {
console.log(key, value); // 输出: a 1, b 2
}
何时仍然使用对象?
- 虽然 Map 在很多方面都优于对象,但对象仍然有其用武之地。
- JSON: JSON 数据格式本质上是对象。
- 简单的配置对象: 对于简单的、静态的配置对象,对象仍然是一个不错的选择。
需要直接访问属性的情况: 如果需要使用 obj.propertyName 语法直接访问属性,对象仍然是必要的。但是,请注意,这可以通过将 Map 转换为对象来实现,但需要权衡性能。