共计 3508 个字符,预计需要花费 9 分钟才能阅读完成。
本文由技术评估与在线 Coding 面试平台 ShowMeBug 技术团队翻译。
在 JavaScript 中,Object
和 Map
都是键值对的动静汇合。尽管两者的定义差不多,但区别也不少。上面跟我一起来看看吧~
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
,你会发现它还有 hasOwnProperty
、isPrototypeOf
、toLocaleString
、toString
等属性。
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
之前。但在检索所有键时,2
在 1
前面。
上面用 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);
//true
smbMap.get(3);
//false
对象则能够用 hasOwnProperty(key)
办法。
smbObj.hasOwnProperty(1);
//true
smbObj.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];
读取键值对数量
Map
有 size
属性来记录外部的键值对数量。
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