Неплохо ли использовать Object.create(null) по сравнению с {}?

Я предпочитаю использовать Object.create(null), поэтому я могу использовать этот объект в качестве простого словаря для хранения основной информации. Если мне нужна функциональность объекта, тогда я бы создал обычный объект, например. var obj = {x:3, etc};

Это потому, что {} не является действительно пустым объектом, поскольку он ссылается на прототип объекта, поэтому в циклах вам нужно сделать hasOwnProperty, чтобы остановить его, танцуя вокруг цепи прототипов, и выполнение этой проверки на каждом цикле затрудняет работу, хотя и незначительно.

Неправильно ли использовать Object.create(null) вместо {}, поэтому мне не нужно писать hasOwnProperty в каждом цикле?

Изменить: возможно дублировать, но я не спрашиваю, как и почему они разные, вместо этого мне интересно узнать, используют ли другие Object.create(null)? Is SOP на земле Javascript?

Изменить 2: Я также предпочитаю выполнять однострочные проверки, например. if(obj[someKey])... ht 'Дань APJ Kalam Sir'.

Ответы

Ответ 1

Насколько мне известно,

{} == Object.create(Object.prototype);

Кроме того,

Мне (только мне) Мне кажется, что Object.create(null) дает вам больше ясности, что ваш объект не наследует ничего i.e its (purely) empty map.


Кроме того,

В обоих случаях вы можете использовать объект в качестве словаря.


Кроме того,

Это зависит от вас, что вы должны делать с вашим объектом.


Когда

  • {} == Object.create(Object.prototype);//вы наследуете все свойства объекта

  • o = Object.create(null);//вы ничего не наследуете. это полностью пустой объект.

Если вы используете объект в качестве карты, и вы создаете объект, используя метод 1 выше, тогда вы должны быть особенно осторожны при выполнении поиска на карте. Поскольку свойства и методы из объекта наследуются, ваш код может работать в случае, когда на карте есть ключи, которые вы никогда не вставляли.

Например, если вы просмотрели toString, вы найдете функцию, даже если вы никогда не ставите ее там. Вы можете обойти это следующим образом:

if (Object.prototype.hasOwnProperty.call(object, 'toString')) {
    // we actually inserted a 'toString' key into object
}

Обратите внимание, что вы не можете просто делать object.hasOwnProperty('toString'), потому что вы можете вставить ключ "hasOwnProperty" в объект, поэтому мы вынуждаем его использовать реализацию в Object.

С другой стороны, если вы используете метод 2 выше, вам не придется беспокоиться о вещах из объекта, появляющихся на карте.

Вы не можете проверить наличие свойства с простым, если:

// Unreliable:
if (object[someKey]) {
    // ...
}

SO,

Чтобы использовать объект как карту, вы используете большинство людей на планете

Object.create(null)//нет накладных расходов, чтобы беспокоиться о наследуемых свойствах.

Во всех остальных случаях вы просто используете

var myObject = {}

MDN - Object.create

MSDN - Object.create

Ответ 2

Не наследуя от Object.prototype с Object.create(null), ваш объект больше не имеет методов на прототипе объекта. Итак, очевидный вопрос: каковы методы этого прототипа и нужны ли вам?

Методы:

  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • toString/<Т26 >
  • valueOf

hasOwnProperty кажется бесполезным, потому что, если нет прототипа, все свойства созданного объекта по определению являются собственными свойствами. Тем не менее, возможно, что некоторая библиотека или другой фрагмент кода может быть итерировать по свойствам объекта с помощью for...in и использовать идиому if (o.hasOwnProperty(key)). Вероятно, слишком много надеяться на то, что он будет использовать более правильные Object.prototype.hasOwnProperty.call(o, key). Такой код теперь терпит неудачу. Или вы можете создать под-объект с созданным объектом в качестве прототипа и быть заинтересованы в знании того, является ли свойство собственным свойством под-объекта или исходит от прототипа.

isPrototypeOf может быть или не быть полезным, если вы планируете использовать созданный объект в качестве прототипа для других объектов и по какой-либо причине хотите проверить, является ли созданный объект или нет в цепочке прототипов таких других объектов.

propertyIsEnumerable не будет использоваться слишком много, но опять же, мы не можем предсказать, что будет делать другой код в системе. Если он пытается вызвать этот метод для созданного объекта или любых объектов, созданных с ним в качестве прототипа, он потерпит неудачу.

То же самое верно для toString. Кто знает, кто может попытаться назвать это на созданном вами объекте? Например, некоторые библиотеки могут попытаться проверить тип значения, выполнив toString и посмотрев, если результат "[object Object]". Надеюсь, они сделают безопасный Object.prototype.toString.call(o), но...

valueOf редко используется явно, но вызывается движком, если ему нужно принудить объект к примитиву. Если он отсутствует, код может сломаться:

> o2 = Object.create(null)
> o2 + 1
Uncaught TypeError: Cannot convert object to primitive value

Конечно, есть вероятность, что кто-то добавил методы к прототипу Object, и в этом случае Object.create({}) подберет их. Возможно, вы не хотите или не нуждаетесь в них. С другой стороны, они, скорее всего, безвредны.

Учитывая все это, кажется, что Object.create(null) следует ограничивать конкретными случаями, когда можно доказать, что ни одна из вышеупомянутых проблем не может возникнуть. Например, когда объект никогда даже не выходит за пределы его локального контекста или никогда не будет использоваться в качестве прототипа для другого объекта. Даже в этом случае преимущество производительности будет очень маленьким или даже нулевым.

Мне интересно узнать, используют ли другие Object.create(null)? Является ли SOP на земле JavaScript?

Я не думаю, что его можно было бы назвать SOP.

Ответ 3

Из книги Вы не знаете JS: этот и прототипы объектов:

Object.create(null) похож на {}, но без Object.prototype, поэтому он "более пустой", чем просто {}.

Object.create(null) - хорошая практика в случае, если вам нужен DMZ (пустой объект для явного привязки: apply & call, bind).

Ответ 4

Вы говорите, что используете Object.create(null) для того, чтобы создать объект, который не наследуется от Object.prototype.

Это как раз пример использования метода Object.create с null в качестве первого аргумента.

Использование {} эквивалентно Object.create(Object.prototype). Много времени мы хотим сделать, поэтому это то, что делает буквальный, но в вашем случае ваш контроль над наследованием более чист.

Если вам нужен какой-либо метод из Object.prototype, вы можете вызвать с помощью .call или .apply в своем объекте

var o = Object.create(null);
Object.prototype.hasOwnProperty.call(o, 'foo'); // some key foo

Ответ 5

Что-то, что не отвечает ни на один из других ответов, заключается в том, что если вы используете {} в качестве словаря, а ваши ключи непредсказуемы (например, ввод от пользователя), тогда вы действительно должны выбрать Object.create(null) или Map поскольку возможно, что присвоение значения определенному ключу с помощью оператора = (т.е. установщик объекта) может бесшумно сбой, поскольку он пытается изменить свойство только для чтения в цепочке прототипов, например, на __proto__ свойство:

let dictObject = {};
let dictNull = Object.create(null);

let key = '__proto__';
dictObject[key] = 'value';
dictNull[key] = 'value';

console.log(dictObject[key] === value);  // false
console.log(dictNull[key] === value);  // true

Чтобы определить свойство __proto__ на Object, вам нужно определить свойство/значение для самого объекта:

Object.assign(dictObject, '__proto__', {value:'value'});

Таким образом, решение в этом случае состоит в использовании Object.create(null) или Map