#javascript
#javascript
Вопрос:
Хорошо известно, что объявление объектов с использованием нотации JSON делает их «наследуемыми» от (или, точнее, построенными как) базового объекта:
myobj={a:1, b:2};
что почти эквивалентно myobj = Object.create(Object); myobj.a=1; myobj.b=2;
и чем:
Object.getPrototypeOf(myobj)
выводит следующее:
Object
__defineGetter__: function __defineGetter__() { [native code] }
__defineSetter__: function __defineSetter__() { [native code] }
__lookupGetter__: function __lookupGetter__() { [native code] }
__lookupSetter__: function __lookupSetter__() { [native code] }
constructor: function Object() { [native code] }
hasOwnProperty: function hasOwnProperty() { [native code] }
isPrototypeOf: function isPrototypeOf() { [native code] }
propertyIsEnumerable: function propertyIsEnumerable() { [native code] }
toLocaleString: function toLocaleString() { [native code] }
toString: function toString() { [native code] }
valueOf: function valueOf() { [native code] }
Однако можно вызвать Object.create()
, null
указав в качестве аргумента:
myobj2 = Object.create(null);
В этом случае будет возвращен пустой прототип:
Object
No Properties
И здесь возникает вопрос: в каких случаях и почему я должен заботиться о том, чтобы разбить цепочку прототипов на оригинал Object
? Где это может быть полезно?
Обновление: как уже исправлено ниже, я имею Object.create(Object.prototype)
в виду, а не Object.create(Object)
то, что вернет Function
объект (действительно Object()
, это функция конструктора для Object
прототипов).
Комментарии:
1. Выбор Nit: это не нотация JSON (которая, кстати, была бы нотацией объекта JavaScript ), а просто объектный литерал . Но, кроме того, это интересный вопрос.
Ответ №1:
Вместо этого:
myobj = Object.create(Object);
… Я думаю, вы имеете в виду, что это эквивалентно:
myobj = Object.create(Object.prototype);
… потому что:
Object.getPrototypeOf( {a:1, b:2} ) === Object.prototype; // true
Что касается того, зачем использовать null
early, если вашему объекту не нужны какие-либо свойства Object.prototype
, досрочное завершение цепочки технически (хотя и незначительно) ускорит поиск свойств, когда свойство не существует для рассматриваемого объекта.
Обратите внимание, что я говорю «рано», потому что цепочка всегда заканчивается null
.
Object.getPrototypeOf( Object.prototype ); // null
obj ----------> proto -------> Object.proto -----> null
--------- --------- -------------
| | | | | |
| foo:1 | | bar:1 | | toString:fn | null
| | | | | |
--------- --------- -------------
^ ^ ^ X
| | | |
obj.foo ------ | | |
^ | | |
obj.bar------- ---------------- | |
^ ^ | |
obj.toString-- ---------------- ------------------ |
^ ^ ^ |
obj.baz------- ---------------- ------------------ ---------------
^---property lookups
Обратите внимание, что baz
свойство не существует нигде в цепочке прототипов.
Из-за этого ему необходимо последовательно искать каждый объект, пока он, наконец, не достигнет null
, прежде чем он поймет, что baz
его нигде не существует.
Если вы удалите Object.prototype
из цепочки, это будет null
немного быстрее.
Комментарии:
1. Итак, ЕСЛИ я вас правильно понял, единственной «очевидной» причиной прототипа являются проблемы с производительностью / полнотой функций?
null
2. @BreakPhreak: Да. Цепочка прототипов всегда заканчивается
null
. Чем раньше вы доберетесьnull
, тем скорее цепочка закончится, остановив поиск свойств. Все остальное (по моей оценке) было бы крайним случаем, например, если бы кто-то по какой-то причине захотелmy_obj instanceof Object; // false
3. Это не только производительность. Иногда вы просто не хотите, чтобы эти свойства были там вообще (например, при реализации хэш-таблицы вам не нужны никакие посторонние ключи)
4. @missingno: не могли бы вы подробнее остановиться на этом?
5. Когда вы хотите использовать объект для хранения пар ключ-значение, имеющих поддельные ключи, такие как hasOwnProperty, и могут быть нежелательными. Хотя и теоретически, поскольку Object.create пока не так широко распространен.