2012-04-26 3 views
5

У меня есть метод, который позволит мне выбрать объект-прототип при создании нового объекта (скопированный с «Javascript: The Good Parts» книги):Javascript поведение прототипа

Object.create = function(o) { 
    var F = function() {}; 
    F.prototype=o; 
    return new F(); 
} 

Теперь говорят, у меня есть объект :

var car = { 
    model: "Nissan" 
}; 

И создать новый объект на основе этого объекта, используя метод "Create":

var car1 = Object.create(car); 

Затем я могу добавить свойство к машине, и оно будет динамически добавляться в car1 (динамическое прототипирование). Так, например:

car.year=2011;  // Gets added to "car"... 
alert(car1.year); // ... Is also avaialable to car1 

Q1) Такое поведение указывает на то, что «год» был добавлен в прототип автомобиля, поэтому он доступен car1. Это верно? Если нет, то где добавляется «год» и почему он доступен как для «автомобилей», так и для «car1»?

Кроме того, за правило делегирования, если метод не может быть найден на объекте, он будет искать свой прототип, а затем проверять все прототипы вверх по цепочке до получения объекта Object.prototype. Итак, если я напечатаю что-то вроде этого:

Object.prototype.originCountry = "Japan"; 
alert(car.originCountry); // Outputs Japan 
alert(car1.originCountry); // Outputs Japan 

Пока все хорошо; Однако, если я делаю:

Object.carColor= "White"; 
alert(car.carColor); // Error! 

Q2) Когда я добавляю свойство «автомобиль» (см car.year пример выше, он будет добавлен прототип автомобиля Тем не менее, когда я добавить свойство. Объект, он не добавляется к объекту своего прототипа? Если это не добавляются, чтобы объект-прототип, то почему он не доступен «автомобиль», в соответствии с правилом делегации?

почему это происходит?

+0

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

+0

Ваш Q2 начинается с неправильного: вы не добавили ничего в прототип 'car', вы добавили его в прототип' car1' (который, оказывается, «автомобиль») – searlea

ответ

5

Когда вы сделаете это:

Object.carColor = "White"; 

Тогда свойство carColor не добавляется к прототипу Object. В настоящее время это свойство Object. Для того, чтобы увидеть, что вы ожидаете, что вы могли бы сделать, это:

Object.prototype.carColor = "White"; 

Тогда после этого:

alert(({}).carColor); // Will alert "White" 

Так что здесь происходит что. любой объект, созданный, включая {} (который представляет собой пустой объект), является новым экземпляром Object и, следовательно, разделяет свойства того, что установлено в прототипе Object.

Как для вашего Object.create функция работает. Давайте посмотрим на это по-умолчанию:

1. var F = function() {}; 

Вы просто создаете новую функцию, по существу, пустой объект. Причина, по которой вы используете функцию, а не что-то вроде {}, состоит в том, что функция может быть связана с вызовом new для создания нового экземпляра этого объекта, в котором функция будет действовать как конструктор.

2. F.prototype=o; 

Вы установили прототип новой пустой функции в объект, который вы создали. Теперь это просто ссылка. Это не глубокая копия. Я имею в виду, что по мере того, как изменяется объект o, будут отображаться все экземпляры объектов (на самом деле они не будут меняться, но они «по-видимому» меняются. Подробнее об этом позже).

3. return new F(); 

Теперь вы просто создаете новый экземпляр этой функции, которая имеет прототип в качестве объекта, который вы передали.

Когда вы делаете следующее:

var car1 = Object.create(car); 

Вы получаете объект car1 который имеет прототип имеет car. Так что, когда вы это делаете:

car.year = 2011 

Не нравится car1 изменения. Это больше похоже на объект, который прототип относится к изменениям. Так что, когда вы делаете что-то вроде:

car1.year 

Поиск производится (первый в прототипе, то в объекте) для свойства под названием year и оказывается, что прототип имеет его и, следовательно, car1.year вернется 2011.

Таким образом, нижняя линия такова:

  1. Прототип делится между экземплярами.
  2. Изменение свойств Object не будет меняться ни при каких обстоятельствах.
+0

Это то, что я пытаюсь Понимаю. В вашем посте вы сказали: [quote] Вы получаете объект car1, у которого есть прототип автомобиля. Поэтому, когда вы это делаете: car.year = 2011 Это не похоже на автомобиль1 меняется. Это больше похоже на объект, который прототип относится к изменениям. [/ quote] Когда я добавляю что-то в «автомобиль» (car.prop = value), почему он добавляется к его прототипу, но когда я делаю то же самое с Object, это не так. @Bergi –

+0

Что в действительности происходит, так это то, что 'car.year = 2011' теперь эквивалентно произнесению' car1.prototype.year = 2011', так как 'car1.prototype' - не что иное, как' car'. –

+0

Извините, что я не знаю об этом, но почему car1.prototype === автомобиль? Функция «create» только устанавливает прототип нового объекта для существующего объекта (в этом случае прототип автомобиля1 указывает на car1) –

1

В первом примере вы добавляете к прототипу своего car1 b ecause car === F.prototype и car1 instanceof F. Итак, к Q1: да.

Object - это функция-конструктор всех объектов, так как F относится к car1. Если вы добавите что-то на Object.prototype, он будет доступен на всех объектах - вот почему вы не должны этого делать, такие неперечислимые свойства испортили все in-in-loops. Если вы устанавливаете свойство функции конструктора Object, ничего не меняется для вещей, которые наследуются от него. Не забывайте: Object соответствует функции F, а не параметру o для настройки прототипа. new Object() - это как Object.create(Object.prototype).

0

Эта функция не позволяет выбрать объект-прототип, он создает конструктор объектов nmew, аргумент объекта в качестве прототипа и затем возвращает новый объект на основе конструктора.

Этот новый объект наследует методы и свойства от аргументов объекта. Это позволяет создавать новые объекты, которые наследуются от других.

Причина это работает (и, кстати, объект представляет собой ядро ​​объектов JavaScript и не должен быть расширен)

Object.prototype.originCountry = "Japan"; 
alert(car.originCountry); // Outputs Japan 
alert(car1.originCountry); 

и это не

Object.carColor= "White"; 

происходит потому, что первый продлить прототип объекта Object, что означает, что построение объекта с помощью конструктора Object наследует эти методы и свойства.

Когда позже мы называем статическую функцию, которая не передается объекту, созданному из конструктора Object.

Я бы рекомендовал прочитать больше о прототипальном наследовании в Javascript. здесь несколько ссылок.

http://www.webreference.com/programming/javascript/prototypal_inheritance/index.html http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=xEJ2PwtH2Oh

http://unscriptable.com/2007/04/17/inheritance-explained/

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