在本教程中,您将了解将键映射到值的 JavaScript Map 对象。
JavaScript Map 对象简介
在 ES6 之前,我们经常使用对象来模拟映射 Map,将键映射到任意类型的值。但是使用对象作为映射有一些副作用:
ES6 提供一个名为 Map
的新集合类型来解决这些缺陷。根据定义,Map
对象保存键值对。键在映射集合中是唯一的。换句话说,Map 对象中的键仅出现一次。Map 的键和值可以是任何值。
迭代 Map
对象时,每次迭代都会返回一个 [key, value]
成员数组。迭代顺序遵循插入顺序,插入顺序对应于 set()
方法每个键值对插入到 Map 的顺序。
要创建新的 Map
,请使用以下语法:
let map = new Map([iterable]);
Map()
接受一个可选的可迭代对象,其元素是键值对。
JavaScript 映射方法
clear()
– 从映射对象中删除所有元素。delete(key)
– 删除指定键的元素。如果该元素在映射中,则返回;如果不在,则返回 false。entries()[key, value]
– 返回一个新的 Iterator 迭代器对象,其中包含映射对象中每个元素的数组。映射中对象的顺序与插入顺序相同。forEach(callback[, thisArg])
– 按插入顺序为映射中的每个键值对调用回调。可选的 thisArg 参数设置每个回调上下文。- get(key) – 返回与键关联的值。如果该键不存在,则返回未定义。
- has(key) – 如果与该键关联的值存在,则返回 true,否则返回 false。
keys()
– 返回一个新的迭代器,其中包含按插入顺序排列的元素的键。set(key, value)
– 设置映射对象指定键的值。它返回映射对象本身,因此您可以将此方法与其他方法链接起来。values()
返回一个新的迭代器对象,其中包含按插入顺序排列的每个元素的值。
JavaScript 映射示例
让我们举一些使用 Map 对象的示例。
创建一个新的映射对象
假设您有一个 user
对象列表,如下所示:
let john = {name: 'John Doe'},
lily = {name: 'Lily Bush'},
peter = {name: 'Peter Drucker'};
假设您必须创建用户和角色的映射。在这种情况下,您使用以下代码:
let userRoles = new Map();
userRoles
是 Map
对象的实例,其类型是对象,如下例所示:
console.log(typeof(userRoles)); // object
console.log(userRoles instanceof Map); // true
将元素添加到映射
要将角色分配给用户,可以使用映射的 set()
方法:
userRoles.set(john, 'admin');
set()
方法将用户 john
与 admin
角色进行映射。由于 set()
方法返回的是映射本身,因此您可以节省一些输入时间。如下例所示:
userRoles.set(lily, 'editor')
.set(peter, 'subscriber');
使用可迭代对象初始化映射
如前所述,您可以将可迭代对象传递给 Map()
构造函数:
let userRoles = new Map([
[john, 'admin'],
[lily, 'editor'],
[peter, 'subscriber']
]);
从映射获取指定键的值
如果你想查看 John
的角色,可以使用映射的 get()
方法:
userRoles.get(john); // admin
如果传递的键不存在,get()
方法将返回 undefined
。
let foo = {name: 'Foo'};
userRoles.get(foo); //undefined
通过键 key 检查元素是否存在
要检查映射中是否存在某个键,请使用映射的 has()
方法。
userRoles.has(foo); // false
userRoles.has(lily); // true
获取映射键值对的数量
映射 size
属性返回 Map 对象的键值对数量。
console.log(userRoles.size); // 3
迭代映射的键
要获取 Map
对象的键,可以使用 keys()
方法。keys()
返回一个新的迭代器对象,其中包含映射中元素的键。
以下示例展示 userRoles
映射对象的用户名。
let john = { name: 'John Doe' },
lily = { name: 'Lily Bush' },
peter = { name: 'Peter Drucker' };
let userRoles = new Map([
[john, 'admin'],
[lily, 'editor'],
[peter, 'subscriber'],
]);
for (const user of userRoles.keys()) {
console.log(user.name);
}
输出:
John Doe
Lily Bush
Peter Drucker
迭代映射值
同样,您可以使用 values()
方法获取映射中包含所有元素值的迭代器对象:
let john = { name: 'John Doe' },
lily = { name: 'Lily Bush' },
peter = { name: 'Peter Drucker' };
let userRoles = new Map([
[john, 'admin'],
[lily, 'editor'],
[peter, 'subscriber'],
]);
for (let role of userRoles.values()) {
console.log(role);
}
输出:
admin
editor
subscriber
迭代映射元素
此外,entries()
方法返回一个迭代器对象,其中包含 Map
对象中每个元素的数组 [key,value]
:
let john = { name: 'John Doe' },
lily = { name: 'Lily Bush' },
peter = { name: 'Peter Drucker' };
let userRoles = new Map([
[john, 'admin'],
[lily, 'editor'],
[peter, 'subscriber'],
]);
for (const role of userRoles.entries()) {
console.log(`${role[0].name}: ${role[1]}`);
}
为了使迭代更加简洁,可以使用解构赋值,如下所示:
let john = { name: 'John Doe' },
lily = { name: 'Lily Bush' },
peter = { name: 'Peter Drucker' };
let userRoles = new Map([
[john, 'admin'],
[lily, 'editor'],
[peter, 'subscriber'],
]);
for (let [user, role] of userRoles.entries()) {
console.log(`${user.name}: ${role}`);
}
除了for...of
循环之外,还可以使用 map 对象的 forEach()
方法:
let john = { name: 'John Doe' },
lily = { name: 'Lily Bush' },
peter = { name: 'Peter Drucker' };
let userRoles = new Map([
[john, 'admin'],
[lily, 'editor'],
[peter, 'subscriber'],
]);
userRoles.forEach((role, user) => console.log(`${user.name}: ${role}`));
将映射键或值转换为数组
有时,您想使用数组而不是可迭代对象,在这种情况下,您可以使用扩展运算符。以下示例将每个元素的键转换为键数组:
var keys = [...userRoles.keys()];
console.log(keys);
输出:
[ { name: 'John Doe' },
{ name: 'Lily Bush' },
{ name: 'Peter Drucker' } ]
以下将元素的值转换为数组:
let roles = [...userRoles.values()];
console.log(roles);
输出
[ 'admin', 'editor', 'subscriber' ]
通过 key 删除一个元素
要删除映射中的元素,请使用映射的 delete()
方法。
userRoles.delete(john);
删除映射的所有元素
要删除 Map
对象中的所有元素,请使用映射 clear()
方法:
userRoles.clear();
因此,现在映射的大小为零。
console.log(userRoles.size); // 0
弱映射
WeakMap
与 Map
类似,只是 WeakMap
的键必须是对象。这意味着当对某个键(对象)的引用超出范围时,相应的值会自动从内存中释放。
WeakMap
仅具有 Map
对象的子集方法:
get(key)
set(key, value)
has(key)
delete(key)
以下是 Map
和 WeekMap
之间的主要区别:
- WeakMap 的元素无法迭代。
- 无法一次清除所有元素。
- 无法获取 WeakMap 的大小。
结论
在本教程中,您学习了如何使用 JavaScript Map 对象及其常用的方法来操作映射中的元素或者键值。