我发现this article建议使用'裸露的物品'如果您的密钥始终是字符串,则需要您的hashmap。
裸对象是使用null
作为原型值创建的对象,例如Object.create(null)
。使用对象文字表示法(即{}
)不会创建裸对象,因为它们将Object.prototype
设置为原型。
文章指出裸机的优点在于你可以将它们用作哈希映射,而不必担心像toString
这样的内置键在使用同名密钥时可能会导致错误。
此行为是ES5和/或ES6标准的一部分吗?也就是说,如果我在代码中使用裸对象作为字符串键哈希映射,我可以依赖我的代码以我期望的方式运行吗?这里有什么警告吗?
答案 0 :(得分:5)
首先,ECMA-Script 2015及以上版本有Map
之类的集合。也就是说,在较新的JavaScript实现中,您不再需要使用对象模拟字典/ hashmaps / hashtables。
文章指出裸体物体的伟大之处在于它 您可以将它们用作哈希图,而不必担心内置 像toString这样的键在使用键时可能会导致错误 同名。
文章忽略了你不需要担心文字对象中的toString
因为有很好的支持函数来获取自己的对象属性而不需要遍历原型链。
例如,假设我已经声明了一个文字对象,如下所示:var obj = { text: "Matias" };
。
常规for..in
循环会迭代Object.prototype
个属性,但Object.keys
只会迭代自己的对象属性:
Object.keys(obj).forEach(propertyName => {
var someOwnProperty = obj[propertyName ];
});
此外,常规for..in
可以Object.keys
使用Object.prototype.hasOwnProperty
:
for(var propertyName in obj) {
if(obj.hasOwnProperty(propertyName)) {
// True if property is declared on obj and not in some
// level of the prototype chain
}
}
更新此处: @bergi对某事感到满意。如果obj
声明了自己的属性hasOwnProperty
,则for..in
以上将无效,因为obj.hasOwnProperty
将不再是Object.prototype.hasOwnProperty
想象一下,您有以下会产生上述问题的对象:
var obj = {
hasOwnProperty: "hey! I'm not Object.prototype.hasOwnProperty anymore!"
};
hasOwnProperty
会隐藏Object.prototype.hasOwnProperty
。
可以使用Object.prototype.hasOwnProperty
直接使用Function.prototype.call
来规避上述问题:
for(var propertyName in obj) {
if(Object.prototype.hasOwnProperty.call(obj, propertyName)) {
// True if property is declared on obj and not in some
// level of the prototype chain
}
}
或者您可以将Object.prototype.hasOwnProperty
存储在变量中,以简化if
语句设置this
使用Function.prototype.bind
调用函数后的内容{/ 1}}:
var hasOwnProperty = Object.prototype.hasOwnProperty.bind(obj);
for(var propertyName in obj) {
if(hasOwnProperty(propertyName)) {
// True if property is declared on obj and not in some
// level of the prototype chain
}
}
虽然您可以使用Object.create(null)
创建裸对象,但当给定的裸对象是其他对象的原型时会出现问题:
var bareObject = Object.create(null, {
text: { value: "hello world" }
});
var secondObject = Object.create(bareObject);
secondObject.text2 = "bye!";
for(var property in secondObject) {
// WAIT, secondObject prototype is a bare object!
// And I can't call secondObject.hasOwnProperty to check
// if the enumerated property is declared in the own object...
}
如果不是这种情况并且给定对象只是裸对象,则可以使用in
运算符:
if("someProperty" in bareObject) {
}
否则,您需要使用Object.prototype.hasOwnProperty
或Function.prototype.call
拨打Function.prototype.bind
,如上所述。
无论如何,正如我在回答的开头所述,如果您正在使用ES2015及更高版本,而您使用的是BabelJS之类的转录程序,则可以使用新的JavaScript标准集合类型用对象模拟字典。
在ECMA-Script 5中引入了此行为是ES5和/或ES6标准的一部分吗?就是说,如果我 在我的代码中使用裸对象作为字符串键哈希映射,我可以依赖我的 代码表现得像我期望的那样?是否有任何警告 这里吗?
Object.create
。它几乎可以在任何现代Web浏览器和NodeJS中运行。
答案 1 :(得分:0)
此行为是ES5和/或ES6标准的一部分吗?
是。您可以找到Object.create(null)
以及在ES5,ES6和ES7标准中密切指定的查找/分配属性的行为。
如果我在代码中使用裸对象作为字符串键哈希映射,我可以依赖我的代码以我期望的方式运行吗?
没有。标准中无法保证将对象实现为散列图,并且也没有复杂性/性能断言。实现可能在大型对象上进行非常慢的属性查找。
从ES6开始,你应该使用保证子线性复杂性的Map
个对象。