JavaScript Map:键值存储与高效查找
JavaScript Map 对象用于存储键值对,并允许任意值(对象、函数、原始值)作为键。需要按插入顺序迭代、使用非字符串键,或频繁新增和删除条目时,应使用 Map。与普通对象不同,Map 的键不会受到继承原型属性影响,这能避免动态字符串键带来的意外冲突。
JavaScript Map 键值存储示例
输出:
输出将显示在这里...
输出:
95
false
2
这个示例如何工作
new Map()创建一个空映射。直接调用Map()而不加new会抛出TypeError。set添加键值对并返回Map实例,因此可以链式调用,例如map.set("a", 1).set("b", 2)。对已有键再次调用set会覆盖值,但不会改变该键在迭代中的位置。get返回已存储的值;如果键不存在,返回undefined。当你要区分“键不存在”和“键存在但值是undefined”时,使用has。size表示当前条目数量;对象则需要Object.keys(obj).length才能得到数量。
JavaScript Map 的常见错误
使用方括号语法而不是 set/get:
错误写法:
const map = new Map();
map["键"] = "值";
console.log(map.get("键")); // undefined
正确写法:
const map = new Map();
map.set("键", "值");
console.log(map.get("键")); // "值"
方括号语法是在 Map 实例上设置对象属性,而不是设置 Map 条目。get、has 和 size 都不会读取这个属性。
误以为对象键按结构相等比较:
错误写法:
const map = new Map();
map.set({id: 1}, "小李");
console.log(map.get({id: 1})); // undefined
正确写法:
const key = {id: 1};
map.set(key, "小李");
console.log(map.get(key)); // "小李"
Map 使用 SameValueZero 进行键相等比较。对对象来说,这意味着按引用身份比较:两个看起来相同的对象字面量仍然是不同的键。
JavaScript Map 与 Object 对比
Map | Object | |
|---|---|---|
| 键类型 | 任意值(对象、函数、原始值) | 仅字符串和 Symbol |
| 迭代顺序 | 插入顺序(有保证) | 大多按插入顺序,但类整数键会先排序 |
| 大小 | map.size | Object.keys(obj).length |
| 原型冲突 | 无 | 键可能遮蔽 toString、constructor 等 |
| JSON 序列化 | 需手动通过 Object.fromEntries | 内置 JSON.stringify |
当键不是字符串、条目需要频繁增删,或你要存储不受信任的键时,使用 Map。固定结构记录或需要 JSON 序列化的数据,使用普通对象。
如果你需要对象但又想避免原型键冲突,可用 Object.create(null) 作为底层对象。
FAQ
JavaScript Map 会保留插入顺序吗?
会。Map 会按键首次插入的顺序迭代条目。对已有键调用 set() 只会更新值,不会改变原位置。删除后再添加同一个键,会把它放到末尾。
JavaScript Map 可以使用对象作为键吗?
可以,但 Map 比较对象键时看的是引用而不是结构。属性完全相同的两个不同对象会被当成两个键。把对象引用保存到变量里,并在 set 和 get 中使用同一个引用。
如何把 JavaScript Map 转成对象或 JSON?
调用 Object.fromEntries(map) 可以创建普通对象,但前提是所有键都是字符串或 Symbol。若有非字符串键,先序列化条目数组:JSON.stringify([...map])。
JavaScript Map 和 JavaScript map() 函数有什么区别?
Map 是用于存取数据的键值集合。JavaScript map() 函数(Array.prototype.map)是数组方法,会对每个元素应用回调并返回新数组。两者同名,但用途完全不同。