在 JavaScript 中,Object 和 Map 都是用于存储 “键值对” 的数据结构,但两者在 键的类型、有序性、迭代方式、性能表现 等核心特性上有显著区别,以下从 6 个关键维度展开对比,并结合场景说明适用场景:
键的类型
- Object:仅支持 字符串 /.Symbol 作为键(其他类型会自动转为字符串,如
1 → "1") - Map:支持 任意类型 作为键(字符串、数字、对象、函数等,键值严格按 “引用 / 值” 比较)
键的有序性
- Object:ES6 前无序,ES6 后按 “插入顺序” 排列(但数字键会优先按大小排序,存在例外)
const obj = {
"a": "aaaa",
"1": "1111",
"b": "bbbb",
"2": "2222"
};
console.log(Object.keys(obj)); // ["1", "2", "a", "b"]
- Map:严格按 插入顺序 排列,迭代时完全遵循插入顺序(无例外)
const map = new Map()
map.set("b", "bbbb")
map.set("1", "1111")
map.set("a", "aaaa")
map.set("2", "2222")
console.log(Array.from(map.keys())); // ["b", "1", "a", "2"](严格按插入顺序)
迭代方式
- Object:需通过
for...in(遍历可枚举属性)、Object.keys()等间接迭代,无法直接遍历键值对
const obj = { name: "张三", age: 80 };
// 方式1:for...in(需过滤原型属性)
for (const key in obj) {
if (obj.hasOwnProperty(key)) { // 避免遍历原型链上的属性(如 toString)
console.log(key, obj[key]); // name 张三;age 80
}
}
// 方式2:Object.entries() 转换为数组后迭代
for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // name 张三;age 80
}
- Map:支持 直接迭代(
for...of、forEach),可直接获取键、值、键值对(entries())
const map = new Map([["name", "张三"], ["age", 80]]);
// 方式1:for...of 遍历键值对
for (const [key, value] of map) {
console.log(key, value); // name 张三;age 80
}
// 方式2:forEach 遍历
map.forEach((value, key) => {
console.log(key, value); // name 张三;age 80
});
// 单独遍历键/值
console.log(Array.from(map.keys())); // ["name", "age"]
console.log(Array.from(map.values())); // ["张三", 80]
键值对数量获取
- Object:需通过
Object.keys(obj).length间接计算(需遍历所有键)
const obj = { name: '李四', age: 99}
console.log(Object.keys(obj).length) // 输出 2
- Map:直接通过
size属性获取(O (1) 时间复杂度,无需遍历)
const map = new Map([['name', '李四'], ['age', 99]])
console.log(map.size) // 2
性能表现
- Object: 存储少量数据时性能稳定,但频繁增删键值对或存储大量数据时,性能较差。底层通过 “隐藏类” 优化属性访问,但频繁添加 / 删除键值对时,隐藏类会频繁重排,导致性能下降。
- Map: 频繁增删、查询大量键值对时性能更优(底层基于哈希表,专门优化了频繁操作)
特殊属性/方法
- 存在原型链继承的 “默认属性”(如
toString、hasOwnProperty),可能与自定义键冲突 - 无原型链,不存在默认属性,键名完全由用户控制(不会冲突)
适用场景
优先用 Object 的场景:
- 存储 简单的键值对(键为字符串,无需复杂类型),如配置项、用户信息(
{ name: "张三", age: 25 }); - 需要 JSON 序列化 / 反序列化(
JSON.stringify(obj)可直接转换 Object,Map 需手动处理为数组后才能序列化); - 浏览器兼容性要求极高(如需兼容 IE 浏览器,Map 不支持 IE)。
优先用 Map 的场景:
- 键为 非字符串类型(如对象、数字、函数),需避免键自动转换导致的冲突;
- 需要 严格按插入顺序迭代 键值对(如日志记录、有序列表);
- 频繁进行 增删、查询操作,或存储 大量键值对(如数据缓存、复杂状态管理);
- 需避免原型链属性冲突(如自定义键名可能与 Object 原型方法重名)。