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

时间:2013-03-20 08:12:35

标签: javascript

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

问题:

与以下内容完全相同:

var p = {}

VS

var p2 = Object.create(null);

5 个答案:

答案 0 :(得分:165)

它们并不等同。 {}.constructor.prototype == Object.prototypeObject.create(null)不会从任何内容继承,因此根本没有属性。

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

{}将等同于Object.create(Object.prototype)


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

enter image description here

答案 1 :(得分:91)

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

  1. var p = {};

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

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

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

  3. 如果您使用对象作为地图,并使用上面的方法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]) {
        // ...
    }
    

    值可能是空字符串,可能是falsenullundefined0NaN等。检查属性是否存在,您仍然需要使用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;
}

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