当前位置: 首页 > Web前端 > JavaScript

彻底理解JavaScript中Object和Map的区别

时间:2023-03-27 16:14:17 JavaScript

本文由技术测评和在线Coding面试平台ShowMeBug技术团队翻译。在JavaScript中,Object和Map都是键值对的动态集合。两者的定义虽然相似,但也有不少不同。跟我一起来看看吧~1.不同的构造方式JavaScript中最简单的Objects创建方式就是通过字面量。constsmbObj={1:'ShowMeBug',2:'ShowMeMoney'};Map是通过内置的构造函数Map创建的。constsmbMap=newMap([[1,'ShowMeBug'],[2,'ShowMeMoney']]);接下来,我将使用“object”或“objectmap”来表示由文字创建的键值集合,“map”是指使用内置构造函数Map创建的映射。2.对象中的key是字符串,map中的key可以是任意类型。对象是键值对的集合,但键只能是字符串。Map的键可以是任何类型。例如,如果将数字用作对象键,则该数字将转换为字符串。因为key已经转成字符串了,所以不管我们得到的是数字1的值还是字符串'1'的值,结果都是一样的。console.log(smbObj[1]);//'ShowMeBug'console.log(smbObj['1']);//'ShowMeBug'和Map的key可以是任意类型,数字1和key字符串'1'键不一样。console.log(smbMap[1]);//'ShowMeBug'console.log(smbMap['1']);//undefined无论是对象还是map,key都是唯一的。对象中不能有两个具有相同键的属性,映射中也不能有两个具有相同键的条目。3.对象将从原型继承冗余键另一个区别是,使用文字创建的对象将从Object.prototype继承一组键值对。打印Object.prototype,你会发现它还有hasOwnProperty、isPrototypeOf、toLocaleString、toString等属性。console.log(Object.prototype);文字创建的对象也将具有这些属性。空对象{}并不是真的空。你可以看看下面的代码。constsocalledEmptyObject={};console.log(socalledEmptyObject['toString']);//?toString(){[nativecode]}我们创建了一个所谓的“空”对象,但能够访问其上的toString键。创建对象映射最好使用Object.create(null)来完成。constemptyObject=Object.create(null);console.log(emptyObject['toString']);//undefinedObject.create(null)可以构造一个没有原型的对象。4.Map会保留键的顺序,但对象不会。键值对的原始顺序将保留在Map中,但不会保留在对象中。constsmbObj={2:'ShowMeMoney',1:'ShowMeBug'};constkeys=Object.keys(smbObj);console.log(keys);//["1","2"]constkeyValuePairs=Object.entries(smbObj);console.log(keyValuePairs);//["1","ShowMeBug"]//["2","ShowMeMoney"]请注意,创建对象时,键2出现在键1之前。但是当检索所有键时,2出现在1之后。让我们使用Map构造函数创建一个类似的集合。这次保留了键的原始顺序。constsmbMap=newMap([[2,'ShowMeMoney'],[1,'ShowMeBug']]);constkeys=smbMap.keys();console.log(keys);//MapIterator{2,1}constkeyValuePairs=smbMap.entries();console.log(keyValuePairs);//MapIterator{2=>"ShowMeMoney",1=>"ShowMeBug"}5.Map提供了一个更好的接口来访问键值对获取访问对象上的属性可以用点或者括号运算符。在本文的示例中,只能使用方括号运算符,因为键是数字。smbObj[1];//'ShowMeBug'在Map上,需要使用get(key)方法获取值。smbMap.get(1);//'ShowMeBug'检测key是否存在Map可以使用has(key)检测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);对象可以使用删除操作符。删除smbObj[1];读取键值对的个数Map有一个size属性记录内部键值对的个数。控制台日志(smbMap.size);该对象没有获取键值对个数的具体方法。我们需要使用外部辅助函数,例如Object.keys()。constsize=Object.keys(smbObj).length;控制台日志(大小);6.对象需要辅助函数来访问键值对。我们可以使用forEach方法来遍历Map中的条目。constsmbMap=newMap([[1,'ShowMeBug'],[2,'ShowMeMoney']]);smbMap.forEach((value,key)=>{console.log(`${key}-${value}`)});//1-ShowMeBug//2-ShowMeMoney至于对象,我们可以迭代Object.entries()辅助函数。Object.entries()将对象的所有属性作为[key,value]键值对的数组返回。一旦你有了这个数组,你就可以使用像forEach这样的数组方法。constsmbObj={1:'ShowMeBug',2:'ShowMeMoney'};Object.entries(smbObj).forEach(([key,value])=>{console.log(`${key}-${value}`)});//1-ShowMeBug//2-ShowMeMoney7.JSON支持对象,但不支持MapconstsmbObj={1:'ShowMeBug',2:'ShowMeMoney'};constjson=JSON.stringify(smbObj);console.log(json);//{"1":"ShowMeBug","2":"ShowMeMoney"}JSON不支持Map,序列化结果为空对象。constsmbMap=newMap([[1,'ShowMeBug'],[2,'ShowMeMoney']]);constjson=JSON.stringify(smbMap);console.log(json);//{}总结JavaScript对象是在其他语言中称为哈希映射。访问映射对象中的键需要O(1)时间,这意味着无论对象映射中的数据量有多少,获取键都需要常数时间。这些键值集合无论是使用Map构造函数还是对象字面量创建的,主要用于快速查找数据,键的访问时间为O(1),检索键不需要扫描所有数据。Map为管理键值对提供了更好的接口。在需要添加和删除条目的场景下,Map是更好的选择。而如果创建一个key-value集合只是用来搜索key的话,对象就足够了。