Map
是 ES6 引入的一种新的集合类型,用于存储键值对。与传统的 JavaScript 对象不同,Map
的键可以是任何类型的值(包括对象、函数、原始类型等),并且它保持键值对的插入顺序。
以下是 Map
的详细介绍,包括其属性、方法和一些常见用法示例。
1. 创建 Map
对象
你可以通过 new Map()
来创建一个空的 Map
,也可以通过传入一个可迭代对象来创建并初始化 Map
。
示例:
// 创建空的 Map
const myMap = new Map();
// 使用数组初始化 Map
const myMap2 = new Map([
['key1', 'value1'],
['key2', 'value2']
]);
console.log(myMap2.get('key1')); // 输出: "value1"
2. Map
的基本属性和方法
2.1 size
属性
size
属性返回 Map
中键值对的数量。
console.log(myMap2.size); // 输出: 2
2.2 set(key, value)
方法
set
方法用于在 Map
中设置键值对。如果键已存在,则更新对应的值。
myMap.set('name', 'Alice');
myMap.set('age', 25);
myMap.set('name', 'Bob'); // 更新键为 'name' 的值
console.log(myMap.get('name')); // 输出: "Bob"
2.3 get(key)
方法
get
方法返回与指定键关联的值。如果键不存在,则返回 undefined
。
console.log(myMap.get('age')); // 输出: 25
console.log(myMap.get('gender')); // 输出: undefined
2.4 has(key)
方法
has
方法返回一个布尔值,表示 Map
中是否存在指定的键。
console.log(myMap.has('name')); // 输出: true
console.log(myMap.has('gender')); // 输出: false
2.5 delete(key)
方法
delete
方法从 Map
中移除指定的键值对。如果键存在且成功删除,返回 true
;否则返回 false
。
console.log(myMap.delete('age')); // 输出: true
console.log(myMap.has('age')); // 输出: false
2.6 clear()
方法
clear
方法用于清空 Map
对象,删除所有的键值对。
myMap.clear();
console.log(myMap.size); // 输出: 0
3. 遍历 Map
Map
提供了多种遍历方法,且遍历顺序与插入顺序一致。
3.1 forEach(callback, thisArg)
forEach
方法遍历 Map
,对每个键值对调用提供的回调函数。
myMap2.forEach((value, key) => {
console.log(key + ': ' + value);
});
// 输出:
// "key1: value1"
// "key2: value2"
3.2 keys()
方法
keys
方法返回一个包含 Map
中所有键的 Iterator
对象。
for (let key of myMap2.keys()) {
console.log(key);
}
// 输出:
// "key1"
// "key2"
3.3 values()
方法
values
方法返回一个包含 Map
中所有值的 Iterator
对象。
for (let value of myMap2.values()) {
console.log(value);
}
// 输出:
// "value1"
// "value2"
3.4 entries()
方法
entries
方法返回一个包含 Map
中所有键值对的 Iterator
对象,键和值分别作为数组的第一和第二个元素。
for (let [key, value] of myMap2.entries()) {
console.log(key + ': ' + value);
}
// 输出:
// "key1: value1"
// "key2: value2"
4. 与对象的对比
-
键的类型:对象的键只能是字符串或符号,而
Map
的键可以是任何类型,包括对象、函数等。 -
插入顺序:
Map
记录键值对的插入顺序,使用for...of
或forEach
遍历时会按插入顺序返回键值对。而对象的属性顺序一般按照插入顺序,但某些情况下可能有不同的顺序。 -
性能:
Map
在频繁的增删操作中通常表现得更好,尤其是包含大量键值对的情况下。
5. 常见用法
5.1 作为缓存
Map
常用于缓存某些计算结果,以便在后续操作中快速访问。
const cache = new Map();
function calculate(num) {
if (cache.has(num)) {
return cache.get(num);
}
const result = num * 2; // 假设这个计算很耗时
cache.set(num, result);
return result;
}
console.log(calculate(5)); // 10
console.log(calculate(5)); // 10, 从缓存中获取
5.2 处理复杂键
Map
支持对象作为键,可以处理复杂的数据结构。
const map = new Map();
const objKey = { id: 1 };
map.set(objKey, 'value associated with object key');
console.log(map.get(objKey)); // 输出: "value associated with object key"
6. WeakMap
除了 Map
,ES6 还引入了 WeakMap
。WeakMap
与 Map
类似,但它的键必须是对象,且对这些对象的引用是弱引用(即,如果没有其他引用指向该对象,垃圾回收器可以回收该对象,即使它是 WeakMap
的键)。
WeakMap
没有 size
属性,也不能枚举其内容(没有 keys()
、values()
、entries()
方法),因为它的键是弱引用,为了保证垃圾回收机制的透明性。