用Object.create(null)创建JS对象?

Roy*_*mir 138 javascript

我知道很多创建JS对象的方法,但我不知道那个Object.create(null).

题:

是完全一样的:

var p = {}
Run Code Online (Sandbox Code Playgroud)

VS

var p2 = Object.create(null);
Run Code Online (Sandbox Code Playgroud)

Pet*_*org 178

他们并不等同.{}.constructor.prototype == Object.prototype虽然Object.create(null)不从任何东西继承,因此根本没有属性.

换句话说:默认情况下,javascript对象继承自Object,除非您使用null作为其原型显式创建它,例如:Object.create(null).

{}相反,它将等同于Object.create(Object.prototype).


在Chrome Devtool中你可以看到它Object.create(null)没有__proto__属性,同时{}也是.

在此输入图像描述


dou*_*536 96

他们肯定不相同.我正在写这个答案,以更全面地解释为什么它会有所作为.

  1. var p = {};

    创建一个继承属性和方法的对象Object.

  2. var p2 = Object.create(null);

    创建一个不继承任何内容的对象.

如果您使用对象作为地图,并使用上面的方法1创建对象,那么在地图中进行查找时必须格外小心.由于Object继承了属性和方法,因此您的代码可能会遇到地图中有从未插入的键的情况.例如,如果你进行了查找toString,你会找到一个函数,即使你从未在那里放过那个值.你可以像这样解决这个问题:

if (Object.prototype.hasOwnProperty.call(p, 'toString')) {
    // we actually inserted a 'toString' key into p
}
Run Code Online (Sandbox Code Playgroud)

注意,分配一些东西很好p.toString,它只会覆盖继承的toString函数p.

请注意,您不能这样做,p.hasOwnProperty('toString')因为您可能已经插入了一个键"hasOwnProperty" p,因此我们强制它使用该实现Object.

另一方面,如果您使用上面的方法2,那么您将不必担心Object出现在地图中的事情.

您无法检查是否存在具有以下简单属性的属性if:

// Unreliable:
if (p[someKey]) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

该值可能是一个空字符串,可能是false,或null,或undefined,或0,或NaN等检查属性是否都存在,你仍然需要使用Object.prototype.hasOwnProperty.call(p, someKey).

  • 检查属性是否存在的更简单的替代方法是:`if(someKey in p){` (5认同)
  • @mrcrowl只有当他们使用`Object.create(null)`时.我不喜欢做那样的假设,即使你使用`Object.create(null)`是完全正确的,代码可以改变,对象可以被替换为在某个时候继承`Object`的对象.`hasOwnProperty`总是有效. (2认同)
  • 我觉得对这样的事情要小心应该是不必要的。我感谢您的回答,但文档应该为您提供处理您正在使用的任何代码所需的 api。如果您从 github 获取一些随机代码,那么您可以将其分叉并避免记录较少的更新。更不用说 `{}` 比 `Object.create(null)` 更普遍,如果您的代码此时不小心获取了继承的属性,您可能需要担心更大的错误。我只能看到人们使用 Object.create(null) 作为次要优化。 (2认同)