2014-10-24 3 views
3

У меня есть объектный литерал внутри, у меня есть другой литерал. Родительские экземпляры устанавливают значения в порядке, но не внутренние. Я смущен этим поведением.
Почему поведение объектного литерала отличается?Логическое поведение создания экземпляра варьируется

вот http://jsfiddle.net/Lq6frf76/

var vehicle={ 
    tires : 0, 
    seats : { 
     total :0 
    } 
} 


var Car = Object.create(vehicle); 
Car.tires=4; 
Car.seats.total = 4 ; 

var bike = Object.create(vehicle); 
bike.tires=2; 
bike.seats.total = 2 ; 




console.log(Car.tires);  --->> it is not overwritten not consistent 
console.log(Car.seats.total); -->> it is overwritten here 

console.log(bike.tires); 
console.log(bike.seats.total); 

enter image description here

Это не дублирует вопрос

  1. Я знал, что альтернативные варианты
  2. Я знал, что внутренний буквальным перекроет я видел много примеров
  3. То, что я не знаю, почему same behavior is not repeated for the parent object или другими словами

    почему значение car.tires показывает правильно, а не перезаписаны в моем примере

+1

нет, это не для меня – Sankara

+0

Я вижу вашу проблему сейчас. Кажется, что «Car.seats.total» не было установлено. На самом деле это не проблема: проблема в том, что 'bike.seats' переписывает' Car.seats'. – lonesomeday

+0

Да, именно это мой вопрос, почему он переписывается? – Sankara

ответ

1

Edit: Добавлено несколько больше на конец и сделал коррекцию

Мне кажется, что нам нужно ответить здесь. Прошу прощения, если это плохой этикет (и если это неправильный ответ). Пожалуйста, дайте мне знать.

Пути Прототипом работает наследование в JavaScript:
Когда вы прочитать свойство объекта, позволяет сказать tires свойства вашего Car объекта, сначала он проверяет Car есть что само свойство. Что это означает, есть ли свойство tires, которое напрямую связано с объектом ? Или, другими словами, это Car что-то вроде этого:

{ 
    tires: 0, 
    ... 
} 

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

function Vehice(t) { 
    this.tires = t; 
    ... 
}; 
var Car = new Vehicle(4); 

Все Object.create() делает делает объект вы передаете в prototype объекта он возвращается к вам.

Таким образом, после Object.create() ваш объект выглядит примерно так

{ 
    __proto__: //reference to vehicle 
} 

Так что, когда он не находит tires непосредственно присоединенные к объекту, он смотрит на прототипе, в этом случае ссылка на vehicle объект, который вы создали ранее. Прототип (vehicle) имеет, имеет свойство tires, поэтому оно возвращает это значение.

Коррекция

Так что же происходит, когда вы говорите Car.tires = 6?Когда вы напишите значение свойства объекта, все будет работать по-другому. Javascript только смотрит, есть ли у объекта этот объект для записи. Если сам объект не имеет этого свойства, он сначала проверяет цепочку прототипов, чтобы убедиться, что свойство не является унаследованным только для чтения. Если это не так, то создает это свойство на самом объекте (до тех пор, пока законно писать это свойство для объекта). Так что теперь у вас есть что-то, что выглядит следующим образом:

{ 
    tires: 6, 
    __proto__: //reference to vehicle 
} 

Конец коррекция

Теперь, когда вы читаете tires свойства на Car объекта, он первый видит tires свойства на самом Car объекта и возвращает это значение, никогда не нужно смотреть на прототип.

Вот почему вы можете установить tires на одном транспортном средстве, а не влиять на стоимость других.

Сейчас для seats.total Недвижимость. Когда вы читаете из свойства seats, все работает по-прежнему. Не существует свойства seats на самом объекте Car, поэтому он смотрит на прототип, который у него есть. Затем он проверяет объект, на который ссылается seats, чтобы увидеть, имеет ли он свойство total, к которому он прикреплен, и он делает это, поэтому он просто возвращает это значение.

Теперь, когда вы хотите написать в собственность total, все снова и снова. Заявление таково: Car.seats.total = 4. Что здесь происходит, так это то, что вы устанавливаете свойство total на объект , на который ссылается seats объект.

Javascript сначала должен найти объект, на который ссылается seats. Он делает это, проверяя, является ли это свойством самого объекта Car. Это не так, поэтому он проверяет прототип, где он находит свойство seats. Теперь он может записать свойство total объекту seats, как мы видели ранее, но обратите внимание, что это происходит с свойством seats прототипа, который является реферином для объекта vehicle, определенного ранее и разделяемого bike.

Другими словами, JavaScript не видит, что вы пишете в собственность Car объекта, поэтому он не создает seats свойство на Car объекта и присвоить ему новый объект, а затем в total собственности на этот объект и назначить его 4.

Теперь, когда вы пытаетесь прочитать bike «s seats свойства, JavaScript сначала ищет, чтобы увидеть, если bike имеет seats свойство непосредственно присоединенную к нему. Это не так, поэтому он выглядит прототипом bike, который имеет его и возвращает измененный объект vehicle.seats.

Надеюсь, это разъяснит, что происходит и отвечает на ваши вопросы. Дайте мне знать, если какая-либо часть не ясна, и я надеюсь, что кто-то меня исправит, если я просто ошибаюсь!

Добавление: Я думаю, исходя из традиционного языка OO, как она работает для tires является то, что можно было бы ожидать, чтобы случиться: Вы унаследовать начальное значение, но если вы измените его, вы не ожидаете, что изменить для каждого другого экземпляра vehicle.

Способ, которым javascript делает это очень экономично. Только изначально у прототипа есть свойство, если у вас есть тысяча объектов, наследующих от vehicle, и только 2 из них устанавливают свойство tires, вы использовали только пространство для трех Number s вместо тысячи.

Что касается, как она работает с seats, я полагаю, что они могли бы спроектировали язык, чтобы обнаружить, если вы настраивали свойство на унаследованные object (seats), а затем скопировать весь объект в экземпляр. Я предполагаю, что это фактически сделает систему менее гибкой и более сложной. Если вы хотите Car иметь свою собственную версию seats, вы можете указать его следующим образом:

var car2 = Object.create(vehicle, { 
    seats: { 
     value: { 
      count: vehicle.seats.total 
     } 
    } 
}); 

или вот так:

var car2 = Object.create(vehicle); 
car2.seats = { count: vehicle.seats.total }; //create a new object like the one attached to vehicle 

, что последний пример сделать ли яснее, что происходит?

Для меня в этом случае явная версия конструктора этого будет более естественной, но с javascript мы можем использовать конструкторы или `Object.create() или различные комбинации из них, чтобы делать то, что нам нужно.

В конечном счете, каждый комплект происходит в двух частях. Сначала найдите объект, на который мы устанавливаем свойство; Наконец, установите свойство. Все до этого окончательного . только там, чтобы сделать первый шаг:

Car.seats.count = 10 означает установить count свойство объекта, указанного на Car.seats 10. Какой объект является Car.seats? Мы теперь следуем правилам , читающим свойство, а не письмо. Car не имеет свойства seats, поэтому см., Если он наследует один. Если это не так, Car.seats вернет undefined, и попытка установить свойство на undefined вызовет ошибку. Если он наследует его, Car.seats вернет объект откуда-то вниз по цепочке прототипов, в этом случае объект, на который ссылается vehicle. Этот объект имеет свойство count так просто установить его на 10.

Car.tires = 4 означает установить tires свойства объекта, указанный на Car до 4. Car не имеет tires свойства, поэтому убедитесь, что мы позволили создать один, а затем сделать это.

Надеюсь, это прояснит ситуацию. Извините за то, что написал так много, но это действительно помогло укрепить эти концепции для меня. Плюс я узнал некоторые материалы ECMAScript 5, которые я блаженно игнорировал :-)