2013-03-29 2 views
1

в Firebug консоли:Путаница цепи прототипов, примитивы и объекты

>>> a=12 
12 
>>> a.__proto__ 
Number {} 
>>> (12).__proto__ 
Number {} 
>>> a.constructor.prototype === (12).__proto__ 
true 
>>> a.constructor.prototype.isPrototypeOf(a) 
false 

последняя строка вызывает у меня большую путаницу по сравнению с другими линиями. также см. Constructor.prototype not in the prototype chain?

ответ

2

Когда вы используете оператор . с примитивом, язык автоматически устанавливает его в соответствующий тип объекта (в данном случае - Number). Это потому, что простые примитивные типы в JavaScript действительно не являются экземплярами объекта.

Таким образом, фактическая левая сторона

a.__proto__ 

не число 12, но по существу new Number(12). Однако переменная «a» продолжает оставаться простым значением 12.

Section 8.7 of the spec «объясняет» это типичным языком языка ECMA 262. Я не могу найти четкий абзац, в котором описывается, как примитив baseValue рассматривается как экземпляр Number, Boolean или String, но этот раздел непосредственно подразумевает его. Я думаю, что потому, что эти не примитивные синтетические значения являются эфемерными (они только «реальные», в то время как вычисляется выражение . или []), что спецификация просто говорит о поведении, не требуя явного требования о создании фактического числа. Однако я догадываюсь об этом.

+0

Вы были бы еще добрее и, возможно, дали бы ссылку на спецификации ECMA для этого преобразования? –

+0

@ ashy_32bit обязательно - я обновлю ответ – Pointy

+0

Я буду голосовать как стимулятор;) –

1

@Pointy объяснил это очень хорошо. В принципе, если вы хотите, чтобы ваше последнее заявление, чтобы быть правдой, вы должны написать это как:

a.constructor.prototype.isPrototypeOf(new Number(a)); 
0

В примитивов JavaScript не имеет цепи прототипов. Только объекты. Примитивное значение включает в себя:

  1. BOOLEANS
  2. Числа
  3. Строки
  4. Null
  5. Неопределенное

Следовательно, если вы звоните isPrototypeOf с примитивным значением, то он будет всегда возвращать false ,

Если вы попытаетесь использовать логическое число или строку в качестве объекта, то JavaScript автоматически принуждает его к объекту для вас. Следовательно, a.constructor оценивает new Number(a).constructor за кулисами. Именно по этой причине вы можете использовать примитивное значение как объект.

Если вы хотите использовать переменную, хранящую примитивное значение как объект часто, то лучше явно сделать его объектом. Например, в вашем случае было бы лучше определить a как new Number(12). Преимущества заключаются в следующем:

  1. JavaScript не требует принуждения примитива к объекту каждый раз, когда вы пытаетесь использовать его в качестве объекта. Вы только создаете объект один раз. Следовательно, это эффективная производительность.
  2. Метод isPrototypeOf в вашем случае вернет true как a будет примером Number. Следовательно, в цепочке прототипов будет Number.prototype.