本文由技术评估与在线 Coding 面试平台 ShowMeBug 技术团队翻译。

在 JavaScript 中,ObjectMap 都是键值对的动静汇合。尽管两者的定义差不多,但区别也不少。上面跟我一起来看看吧~

1.结构形式不同

在 JavaScript 中创立 Object 最简略的办法是通过字面量。

const smbObj = {  1: 'ShowMeBug',  2: 'ShowMeMoney'  };

Map 则是通过内置构造函数 Map 创立。

const smbMap = new Map([  [1, 'ShowMeBug'],  [2, 'ShowMeMoney']]);

接下来,我会用“对象”或“对象映射”来示意通过字面量创立的键值汇合,用“映射”来示意通过内置构造函数 Map 创立的映射。

2.对象中的键是字符串,映射中的键能够是任意类型

Object 是键值对的汇合,但键只能是字符串。而 Map 的键能够是任意类型。

比方,如果用数字作 Object 的键,则该数字将转换为字符串。

因为键曾经被转换成字符串,所以无论咱们是获取数字 1 还是字符串 '1' 的值时,失去的后果都一样。

console.log(smbObj[1]);//'ShowMeBug'console.log(smbObj['1']);//'ShowMeBug'

Map 的键能够为任意类型,数字 1 的键和字符串 '1' 的键并不一样。

console.log(smbMap[1]);//'ShowMeBug'console.log(smbMap['1']);//undefined

无论是对象还是映射,键都是惟一的。对象中不能有两个雷同键的属性,映射中也不能有两个雷同键的条目。

3.对象会从原型中继承多余的键

另一个区别是,应用字面量创立的 Object 会继承一组来自 Object.prototype 的键值对。

打印 Object.prototype,你会发现它还有 hasOwnPropertyisPrototypeOftoLocaleStringtoString 等属性。

console.log(Object.prototype);

通过字面量创立的 Object 也会有这些属性。空对象 {} 并不是真的为空。能够看看下列代码。

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

咱们创立了一个所谓的“空”对象,却可能拜访其上的 toString 键。创建对象映射最好是用 Object.create(null) 来做。

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

Object.create(null) 能构建出没有原型的对象。

4.Map 会保留键的程序,对象不会

键值对的原始程序会在 Map 中失去保留,而在对象中则不会。

const smbObj = {  2: 'ShowMeMoney',  1: 'ShowMeBug'  };const keys = Object.keys(smbObj);console.log(keys);//["1", "2"]const keyValuePairs = Object.entries(smbObj);console.log(keyValuePairs);//["1", "ShowMeBug"]//["2", "ShowMeMoney"]

留神,创建对象时,键 2 呈现在键 1 之前。但在检索所有键时,21 前面。

上面用 Map 构造函数创立一个相似的汇合。这一次键的初始程序失去了保留。

const smbMap = new Map([  [2, 'ShowMeMoney'],  [1, 'ShowMeBug']]);const keys = smbMap.keys();console.log(keys);//MapIterator {2, 1}const keyValuePairs = smbMap.entries();console.log(keyValuePairs);//MapIterator {2 => "ShowMeMoney", 1 => "ShowMeBug"}

5.Map 提供了更好的接口来拜访键值对

获取

拜访对象上的属性能够通过点运算符或方括号运算符来实现。在本文的例子中,因为键用的是数字,所以只能用方括号运算符。

smbObj[1];//'ShowMeBug'

而在 Map 上,则须要用 get(key) 办法来获取值。

smbMap.get(1);//'ShowMeBug'

查看键是否存在

Map 能够用 has(key) 来查看键是否存在。

smbMap.has(1);//truesmbMap.get(3);//false

对象则能够用 hasOwnProperty(key) 办法。

smbObj.hasOwnProperty(1);//truesmbObj.hasOwnProperty(3);//false

增加键值对

set(key, value)Map 中增加新的键值对。

smbMap.set(3, 'ShowMeFeature'); //{1=>'ShowMeBug', 2=>'ShowMeMoney', 3=>'ShowMeFeature'}

而对于对象,咱们应用方括号或点运算符来增加新的键值对。

smbObj[3] = 'ShowMeFeature';//{ 1: 'ShowMeBug', 2: 'ShowMeMoney', 3: 'ShowMeFeature'};

删除键值对

Map 能够通过 delete(key) 办法来删除键值对。

smbMap.delete(1);

对象则能够用 delete 操作符。

delete smbObj[1];

读取键值对数量

Mapsize 属性来记录外部的键值对数量。

console.log(smbMap.size);

对象没有获取键值对数量的特定办法。咱们须要应用像 Object.keys() 这样的内部帮忙函数。

const size = Object.keys(smbObj).length;console.log(size);

6.对象须要帮忙函数来拜访键值对

咱们能够用 forEach 办法遍历 Map 中的条目。

const smbMap = new Map([  [1, 'ShowMeBug'],  [2, 'ShowMeMoney']]);smbMap.forEach((value, key)=>{   console.log(`${key} - ${value}`)});//1 - ShowMeBug//2 - ShowMeMoney

至于对象,咱们能够用 Object.entries() 辅助函数进行迭代。

Object.entries() 会以 [key, value] 键值对数组的模式返回对象的所有属性。一旦拿到这一数组,就能用 forEach 这样的数组办法了。

const smbObj = {  1: 'ShowMeBug',  2: 'ShowMeMoney'  };Object  .entries(smbObj)  .forEach(([key, value])=>{    console.log(`${key} - ${value}`)  });//1 - ShowMeBug//2 - ShowMeMoney

7.JSON反对对象,但不反对 Map

const smbObj = {  1: 'ShowMeBug',  2: 'ShowMeMoney'  };const json = JSON.stringify(smbObj);console.log(json);//{"1":"ShowMeBug","2":"ShowMeMoney"}

JSON 不反对 Map,序列化的后果是一个空对象。

const smbMap = new Map([  [1, 'ShowMeBug'],  [2, 'ShowMeMoney']]);const json = JSON.stringify(smbMap);console.log(json);//{}

总结

JavaScript 中的对象在其余语言中被称为哈希映射。拜访映射对象中的键所需工夫为 O(1),这意味着获取键所需的工夫为常量,而不论对象映射中的数据量如何。

不论这些键值汇合是用 Map 构造函数还是对象字面量创立的,它们都次要用于疾速搜寻数据,键的拜访工夫都是 O(1),检索键也不须要扫描所有数据。

Map 为治理键值对提供了更好的接口。在须要增加和删除条目标场景中,Map 是更好的抉择。而如果创立键值汇合只是用来搜寻键时,对象就够了。

原文链接:7 Differences between Objects and Maps in JavaScript