Создание объекта JS с Object.create(null)?

Я знаю много способов создания объектов JS, но я не знал Object.create(null).

Вопрос:

это точно так же, как:

var p = {}

против

var p2 = Object.create(null);

?

Ответ 1

Они не эквивалентны. {}.constructor.prototype == Object.prototype тогда как Object.create(null) ни от чего не наследуется и, таким образом, вообще не имеет свойств.

Другими словами: объект javascript наследуется от Object по умолчанию, если вы явно не создадите его с нулем в качестве прототипа, например: Object.create(null).

Вместо этого {} будет эквивалентно Object.create(Object.prototype).


В Chrome Devtool вы можете видеть, что Object.create(null) не имеет свойства __proto__, а {} -.

enter image description here

Ответ 2

Они определенно не эквивалентны. Я пишу этот ответ, чтобы более подробно объяснить, почему это имеет значение.

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

Ответ 3

Создание объектов с помощью {} создаст объект, прототип которого - Object.prototype который наследует базовые функции от прототипа Object а создание объектов с помощью Object.create(null) создаст пустой объект, прототип которого равен нулю.

Ответ 4

Если кто-то ищет реализацию 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;
}

Примечание: я написал это из любопытства, и оно написано только в простых терминах, например, я не передаю дескрипторы свойств из второго объекта в возвращаемый объект.