Я знаю много способов создания объектов JS, но я не знал Object.create(null)
.
Вопрос:
это точно так же, как:
var p = {}
против
var p2 = Object.create(null);
?
Я знаю много способов создания объектов JS, но я не знал Object.create(null)
.
Вопрос:
это точно так же, как:
var p = {}
против
var p2 = Object.create(null);
?
Они не эквивалентны. {}.constructor.prototype == Object.prototype
тогда как Object.create(null)
ни от чего не наследуется и, таким образом, вообще не имеет свойств.
Другими словами: объект javascript наследуется от Object по умолчанию, если вы явно не создадите его с нулем в качестве прототипа, например: Object.create(null)
.
Вместо этого {}
будет эквивалентно Object.create(Object.prototype)
.
В Chrome Devtool вы можете видеть, что Object.create(null)
не имеет свойства __proto__
, а {}
-.
Они определенно не эквивалентны. Я пишу этот ответ, чтобы более подробно объяснить, почему это имеет значение.
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)
.
Создание объектов с помощью {}
создаст объект, прототип которого - Object.prototype
который наследует базовые функции от прототипа Object
а создание объектов с помощью Object.create(null)
создаст пустой объект, прототип которого равен нулю.
Если кто-то ищет реализацию 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;
}
Примечание: я написал это из любопытства, и оно написано только в простых терминах, например, я не передаю дескрипторы свойств из второго объекта в возвращаемый объект.