我知道很多创建 JS 对象的方法,但我不知道那个Object.create(null)
。
问题:
是否与以下内容完全相同:
var p = {}
对比
var p2 = Object.create(null);
?
我知道很多创建 JS 对象的方法,但我不知道那个Object.create(null)
。
问题:
是否与以下内容完全相同:
var p = {}
对比
var p2 = Object.create(null);
?
它们不是等价的。{}.constructor.prototype == Object.prototype
whileObject.create(null)
不继承任何东西,因此根本没有属性。
换句话说:一个javascript对象默认继承自Object,除非你明确地用null作为它的原型来创建它,比如:Object.create(null)
。
{}
而是等效于Object.create(Object.prototype)
.
在 Chrome Devtool 中,您可以看到它Object.create(null)
没有__proto__
属性,而{}
有。
它们绝对不是等价的。我写这个答案是为了更全面地解释为什么它会有所作为。
var p = {};
创建一个从 继承属性和方法的对象Object
。
var p2 = Object.create(null);
创建一个不继承任何东西的对象。
如果您将对象用作地图,并且使用上面的方法 1 创建了对象,那么在地图中进行查找时必须格外小心。由于Object
继承了 from 的属性和方法,因此您的代码可能会遇到映射中存在您从未插入的键的情况。例如,如果您对 进行了查找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
, or null
, or undefined
, or 0
, orNaN
等。要检查属性是否存在,您仍然需要使用Object.prototype.hasOwnProperty.call(p, someKey)
.
通过 using 创建对象{}
将创建一个原型为的对象,该对象Object.prototype
继承了Object
原型的基本功能,而通过 using 创建对象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;
}
注意:出于好奇,我写了这个,并且只是用简单的术语来写,例如,我没有将属性描述符从第二个对象转移到返回对象。
当您使用 Object.create(null) 创建一个对象时,这意味着您正在创建一个没有原型的对象。这里的null表示原型链的结束。然而,当您创建像 {} 这样的对象时,将添加对象原型。因此,这是两个不同的对象,一个有原型另一个没有原型。希望这会有所帮助