【发布时间】:2013-03-20 08:12:35
【问题描述】:
我知道很多创建 JS 对象的方法,但我不知道 Object.create(null) 的方法。
问题:
是否完全一样:
var p = {}
对
var p2 = Object.create(null);
?
【问题讨论】:
标签: javascript
我知道很多创建 JS 对象的方法,但我不知道 Object.create(null) 的方法。
问题:
是否完全一样:
var p = {}
对
var p2 = Object.create(null);
?
【问题讨论】:
标签: javascript
它们绝对不是等价的。我写这个答案是为了更全面地解释为什么它会有所作为。
var p = {};
创建一个从Object 继承属性和方法的对象。
var p2 = Object.create(null);
创建一个不继承任何东西的对象。
如果您将对象用作地图,并且使用上述方法 1 创建了对象,则在地图中查找时必须格外小心。因为来自Object 的属性和方法是继承的,所以您的代码可能会遇到映射中存在您从未插入的键的情况。例如,如果您在toString 上进行了查找,您会找到一个函数,即使您从未将那个值放在那里。你可以像这样解决这个问题:
if (Object.prototype.hasOwnProperty.call(p, 'toString')) {
// we actually inserted a 'toString' key into p
}
请注意,可以给p.toString 赋值,它只会覆盖p 上继承的toString 函数。
请注意,您不能只使用p.hasOwnProperty('toString'),因为您可能已将密钥“hasOwnProperty”插入p,因此我们强制它使用Object 中的实现。
另一方面,如果你使用上面的方法2,那么你就不用担心Object会出现在地图上。
您无法使用简单的if 来检查属性是否存在,如下所示:
// Unreliable:
if (p[someKey]) {
// ...
}
该值可能是一个空字符串,可能是false,或null,或undefined,或0,或NaN,等等。要检查一个属性是否存在,你会仍然需要使用Object.prototype.hasOwnProperty.call(p, someKey)。
【讨论】:
if (someKey in p) {
Object.create(null) 时。我不想做这样的假设,即使你完全正确地认为它使用了Object.create(null),代码可能会改变,对象可能会被替换为在某些时候继承Object 的对象。 hasOwnProperty 始终有效。
{} 比Object.create(null) 更普遍,如果您的代码此时意外地获取了继承的属性,您可能需要担心更大的错误。我只能看到人们使用 Object.create(null) 作为次要优化。
!!p[key] 适用于 Object.create(null)。不过hasKey = (key, input) => Object.prototype.hasOwnProperty.call(input, key)也不错
p 中的任何方法,因为每个方法都可以插入,因此变得不安全。
使用{}创建对象将创建一个原型为Object.prototype的对象,它继承了Object原型的基本功能,而使用Object.create(null)创建对象将创建一个原型为null的空对象。
【讨论】:
如果有人正在寻找实现Object.create(null),只是想知道它是如何工作的。它是使用非标准的__proto__ 编写的,因此,我不推荐它。
function objectCreateMimic()
{
/*optional parameters: prototype_object, own_properties*/
var P = arguments.length>0?arguments[0]:-1;
var Q = arguments.length>1?arguments[1]:null;
var o = {};
if(P!==null && typeof P === "object")
{
o.__proto__ = P;
}
else if(P===null)
{
o.__proto__ = null;
}
if(Q!==null && typeof Q === "object")
{
for(var key in Q)
{
o[key] = Q[key];
}
}
return o;
}
注意:出于好奇,我写了这个,而且只是用简单的术语来写,例如,我没有将属性描述符从第二个对象转移到返回对象。 p>
【讨论】:
__proto__ 现在将 officially 成为该语言的一部分。
-1 在 arguments.length>0?arguments[0]:-1;?
Object 原型。这里的变量名可能会好很多。
当您使用 Object.create(null) 创建一个对象时,这意味着您正在创建一个没有原型的对象。null 此处表示原型链的结束。然而,当您创建像 {} 这样的对象时,将添加对象原型。 因此,这是两个不同的对象,一个有原型另一个没有原型。希望这会有所帮助
【讨论】: