我知道很多创建JS对象的方法,但我不知道Object.create(null)
的那些。
问题:
与以下内容完全相同:
var p = {}
VS
var p2 = Object.create(null);
答案 0 :(得分:165)
它们并不等同。 {}.constructor.prototype == Object.prototype
而Object.create(null)
不会从任何内容继承,因此根本没有属性。
换句话说:默认情况下,javascript对象继承自Object,除非您使用null作为其原型显式创建它,例如:Object.create(null)
。
{}
将等同于Object.create(Object.prototype)
。
在Chrome Devtool中,您可以看到Object.create(null)
没有__proto__
属性,而{}
则属性。
答案 1 :(得分:91)
他们肯定不等同。我正在写这个答案,以更全面地解释为什么它会有所作为。
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
,它只会覆盖toString
上的继承p
函数。
请注意,您不能只执行p.hasOwnProperty('toString')
,因为您可能已将一个键“hasOwnProperty”插入p
,因此我们强制它使用Object
中的实现。
另一方面,如果您使用上面的方法2,那么您不必担心地图中出现Object
的内容。
您无法检查是否存在具有此类简单if
的属性:
// Unreliable:
if (p[someKey]) {
// ...
}
值可能是空字符串,可能是false
,null
,undefined
,0
或NaN
等。检查属性是否存在,您仍然需要使用Object.prototype.hasOwnProperty.call(p, someKey)
。
答案 2 :(得分:0)
使用{}
创建对象将创建一个对象,其原型为Object.prototype
,继承Object
原型的基本函数,而使用Object.create(null)
创建对象将创建一个空原型为null的对象。
答案 3 :(得分:0)
使用Object.create(null)创建对象时,这意味着您正在创建没有原型的对象。 null 在这里表示原型链的末尾。但是,当您创建类似{}的对象时,将添加对象原型。 因此,这是两个不同的对象,一个带有原型,另一个没有原型。希望这会有所帮助
答案 4 :(得分:-1)
如果有人正在寻找实现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;
}
注意:我出于好奇而写了这个,并且它只是用简单的术语编写的,例如,我没有将属性描述符从第二个对象传递给返回对象。