2013-06-14 3 views
3
function Foo() {} 
Foo.prototype.x = 1 

foo = new Foo() 
foo2 = new Foo() 

foo2.x = 2 
Foo.prototype.x = 3 

console.log("foo.x = ", foo.x) 
console.log("foo2.x = ", foo2.x) 
=> foo.x = 3 
=> foo2.x = 2 

Два объекта созданы выше, inherited property одного объекта обновляется, то их prototype's property обновляется. Почему обновленный объект сохраняет свое новое значение, а другой трек prototype's?Update прототипа после создания объекта

@EDIT

Выражение выше, the inherited property of one object is updated, кажется, вводит в заблуждение в приведенном выше контексте.

В самом деле, shadow property будет создан на object, когда локально несуществующие property установлен, даже если prototype уже содержит его. В этом случае prototype's properties готовы только с точки зрения object. Впоследствии это local shadow property имеет непосредственное право на доступ.

+0

Потому что Javascript работает так. Если свойство не найдено в объекте, оно выполняется через цепочку прототипов объекта. – MaxArt

ответ

4

Почему обновленный объект сохраняет свое новое значение, а другой - прототип?

Поскольку x свойство непосредственно устанавливается на foo2 и тениx собственности прототипа.

ли console.dir(foo2) и посмотреть на себя:

Foo 
    x: 2 
    __proto__: Foo 
    constructor: function Foo() {} 
    x: 3 
    __proto__: Object 

принимая во внимание, console.dir(foo) показывает:

Foo 
    __proto__: Foo 
    constructor: function Foo() {} 
    x: 3 
    __proto__: Object 

Когда вы пытаетесь получить доступ к свойству, всегда ближе к значению объекта в цепочке прототипов будет возвращаться.

Точный алгоритм можно найти в §8.12.2 of the ECMAScript 5.1 specification.

+0

Спасибо, также выучили 'console # dir' здесь. – sof

+1

Это очень удобно! 'console.log' обычно показывает значение в некотором подходящем человеко-читаемом формате, но' console.dir', кажется, всегда преобразует аргумент в объект и перечисляет все свойства и показывает наследование. Это, безусловно, помогает правильно проверять ценности. –

0

Вы никогда не заходило foo.x, поэтому он принимает значение по умолчанию prototype, который в то время .log(), является 3.

Если вы идете

foo.x = 10 
foo2.x = 2 
Foo.prototype.x = 3 

... затем проверить foo.x, это 10, так как это было явно переопределены.

Как следствие, если не установлен foo2.x, он также будет 3:

... 
//foo2.x = 2 
Foo.prototype.x = 3 
... 

Если что-то не работает так, это будет означать, что .prototype собственность будет доступен только для чтения после того, как , поэтому у вас будут разные версии по умолчанию, которые будут выполняться в зависимости от того, когда вы создали экземпляр и/или изменили свойство. Не весело.

Когда вы явно переопределяете его, вы знаете, когда и почему он изменился. В противном случае используется текущая установка .prototype.

1

JavaScript будет работать только с прототипом, чтобы разрешить вызов свойства, если он не определен конкретно для текущего экземпляра.

С .x определено для foo2 как 2, это не выглядит больше для значения. Однако для обув, .x не определен на экземпляре, так это выглядит с прототипом, и получает 3.

1

Это хороший вопрос, в любом случае ответ прост: потому что foo2 объект имеет свойство с именем x который имеет свою собственную ценность и не унаследован от прототипа. Если вы хотите получить доступ к значению прототипа, вы должны сделать foo1.constructor.prototype.x. Вы должны представить себе структуру, как это:

  • Foo
  • Foo.prototype
    • Foo.prototype.x

переменные выглядеть следующим образом:

  • foo = {}
  • foo2 = {х: 2}

Если JS не найти x свойство в объекте, то это будет выглядеть внутри прототипа.

Смежные вопросы