JavaScript 中对象和map映射之间的 6 个区别

JavaScript中的Object与Map关键差异

Object 和 Map 都是键值对的动态集合,从这个定义开始,它们非常相似,但也可以找出它们之间的一些差异。

1. 构造不同

对象字面量语法是在 JavaScript 中创建对象映射的最简单方法。

const numbersObj={1:"One",2:"Two",};

Map 是使用内置的 Map 构造函数创建的。

constnumbersMap=newMap([[1,"One"],[2,"Two"],]);
console.log(numbersMap);// Map(2) { 1 => 'One', 2 => 'Two' }

从现在开始,使用 object 或 object maps 来表示使用对象字面量语法创建的键值集合,使用 maps 来表示使用 Map 内置构造函数构建的映射。

2. 键名不同

object 的键名是字符串,Map 上的键名可以是任何类型。object 是键值对的集合,并且键只能是字符串。而 Map 的键可以是任何类型。例如,如前面介绍的在对象字面量中使用数字作为键,该数字将会被转换为字符串并用作键。

由于键被转换为字符串,所以在获取对应的键 1 数字值或字符串 '1' 值时,会得到相同的结果。如下:

constnumbersObj={1:"One",2:"Two",};
console.log(numbersObj[1]);// One
console.log(numbersObj["1"]);// One

使用 Map 时,键可以是任何类型,因此 1 数字键不同于'1'字符串键。

constnumbersMap=newMap([[1,"One"],[2,"Two"],]);
console.log(numbersMap.get(1));// One
console.log(numbersMap.get("1"));// undefined

在这两种情况下,键都是唯一的。一个对象中不能有两个具有相同键的属性,或者一个映射中不能有两个具有相同键的元素。

3. 对象拥有原型链属性

这个区别是使用对象字面量创建的对象具有 Object.prototype 的键值对。当打印 Object.prototype 时,可以看到它有一些属性,如 hasOwnProperty、isPrototypeOf、toLocaleString、toString

使用对象的文字语法创建的对象将具有所有这些属性键。所以空对象 {} 并不是真正的空,如下面的代码:

const mapObject={};
console.log(mapObject["toString"]);// ƒ toString() { [native code] }

创建空对象的建议使用 Object.create(null) ,因为 Object.create(null) 可以构建一个没有 prototype 的对象。

const mapObject=Object.create(null);
console.log(mapObject["toString"]);// undefined

4. Map 保留键的顺序,Object 不会

在映射 Map 中将会保留键值对在定义时的原始顺序,而在对象 Object 中则不会。

const numbersObj={2:"Two",1:"One",};
const keys=Object.keys(numbersObj);console.log(keys);// [ '1', '2' ]
const keyValuePairs=Object.entries(numbersObj);console.log(keyValuePairs);// [ [ '1', 'One' ], [ '2', 'Two' ] ]

如上代码所示,创建对象时,键 2 位于键 1 之前,而在检索所有键时,键 2 位于 1 之后。

下面是使用 Map 构造函数构建的类似集合,如下:

const numbersMap=newMap([[2,"Two"],[1,"One"],]);
const keys=numbersMap.keys();console.log(keys);// [Map Iterator] { 2, 1 }
const keyValuePairs=numbersMap.entries();
console.log(keyValuePairs);// [Map Entries] { [ 2, 'Two' ], [ 1, 'One' ] }

5. Map 操作接口更加友好

对象 Object 获取键的名称需要辅助函数获取,而映像 Map 拥有更加友好的接口,如 add、get、has 等等。

6. JSON 支持对象 Object 但不支持映像 Map

在 JSON 数据处理方面,相关的函数进支持对象 Object 但不支持映像 Map 。

const numbersMap=newMap([[2,"Two"],[1,"One"],]);
const json=JSON.stringify(numbersMap);
console.log(json);// {}

而 Object 可以,如下:

const numbersObj={2:"Two",1:"One",};
const json=JSON.stringify(numbersObj);
console.log(json);// {"1":"One","2":"Two"}

总结

对象 Object 和映像 Map 是 JavaScript 中常见的两种数据类型,对象 Object 在其他语言中被称为哈希映射。访问对象中的键具有 O(1) 访问时间,这意味着无论对象中的数据量如何,获取键都需要恒定时间。

无论这些键值集合是如何使用 Map 构造函数或对象字面量语法创建的,它们主要用于快速搜索数据。

无论这些键值集合是如何使用 Map 构造函数或对象文字语法创建的,它们主要用于快速搜索数据。它们都在 O(1) 访问时间内执行,而 Map 检索键不需要扫描所有的数据。

Map 提供了一个更好的接口来管理键值对,在需要频繁添加和删除条目的场景中,Map 将是更好的选择。

原文: JavaScript 中对象和映射之间的 6 个区别 - 知乎 (zhihu.com)

JavaScript 中的普通对象(Object) Map 对象虽然都可以用于存储键值对,但在功能、使用方式适用场景上有显著区别。 普通对象的键必须是字符串或 Symbol 类型,而 Map 允许使用任何类型的值(包括对象、函数、甚至 undefined)作为键[^3]。这种灵活性使得 Map 更适合需要将对象或其他非字符串值作为键的情况。例如,可以将一个 DOM 元素作为键,关联其相关的数据,而无需担心与其他键名冲突。 Map 是有序的,即键值对的插入顺序会被保留,而普通对象的键值对顺序是不确定的(尽管现代浏览器通常按照插入顺序来处理,但这不是语言规范所保证的)。这意味着如果需要依赖键值对的顺序进行操作,Map 是更可靠的选择。 Map 提供了更丰富的 API 来操作数据,如 `set()`、`get()`、`has()`、`delete()` `clear()`,这些方法使得对 Map 的增删改查操作更加直观高效。相比之下,普通对象虽然也可以通过 `Object.assign()`、`delete` 等方法操作,但功能相对有限,且某些操作需要额外的代码来实现。例如,要获取普通对象的大小,需要手动计算键的数量,而 Map 提供了 `size` 属性直接返回键值对的数量[^3]。 普通对象可以直接使用字面量语法进行初始化,而 Map 必须通过 `new Map()` 构造函数创建,并且如果希望初始化时包含数据,需要传入一个可迭代对象(如数组),其中每个元素都是一个键值对数组。例如: ```javascript const obj = { name: 1, age: 2 }; const map = new Map([ ['name', 1], ['age', 2] ]); ``` 普通对象可以使用 `JSON.stringify()` 进行序列化,生成 JSON 字符串,而 Map 不能直接序列化,需要先将其转换为数组或普通对象才能进行序列化[^2]。这在需要将数据保存为 JSON 格式时是一个限制,但可以通过自定义转换逻辑来解决。 此外,Map 不会与原型链上的属性发生冲突,因为 Map 实例本身不会继承任何键值对。而普通对象可能会受到原型链上同名属性的影响,例如如果一个对象的原型上有一个 `toString` 方法,那么该对象本身就不能安全地使用 `toString` 作为键名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值