169

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

问题:

是否与以下内容完全相同:

var p = {}

对比

var p2 = Object.create(null);

?

4

5 回答 5

225

它们不是等价的。{}.constructor.prototype == Object.prototypewhileObject.create(null)不继承任何东西,因此根本没有属性。

换句话说:一个ja​​vascript对象默认继承自Object,除非你明确地用null作为它的原型来创建它,比如:Object.create(null)

{}而是等效于Object.create(Object.prototype).


在 Chrome Devtool 中,您可以看到它Object.create(null)没有__proto__属性,而{}有。

在此处输入图像描述

于 2013-03-20T08:37:19.000 回答
104

它们绝对不是等价的。我写这个答案是为了更全面地解释为什么它会有所作为。

  1. var p = {};

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

  2. 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).

于 2014-01-12T19:29:21.613 回答
1

通过 using 创建对象{}将创建一个原型为的对象,该对象Object.prototype继承了Object原型的基本功能,而通过 using 创建对象Object.create(null)将创建一个原型为 null 的空对象。

于 2018-04-12T19:16:53.107 回答
0

如果有人正在寻找实施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;
}

注意:出于好奇,我写了这个,并且只是用简单的术语来写,例如,我没有将属性描述符从第二个对象转移到返回对象。

于 2014-11-19T06:51:34.713 回答
0

当您使用 Object.create(null) 创建一个对象时,这意味着您正在创建一个没有原型的对象。这里的null表示原型链的结束。然而,当您创建像 {} 这样的对象时,将添加对象原型。因此,这是两个不同的对象,一个有原型另一个没有原型。希望这会有所帮助

于 2020-05-27T04:12:03.533 回答