Тонкости создания прототипов
Друзья, подскажите, почему этот вариант прототипа не делает доступной функцию getTags, а тот который закомментирован - да?
function Element(){ if( typeof Element.getTags !== "function"){ //Element.prototype.getTags = function( elem ){ console.log( elem );} Element.prototype = { constructor: Element, getTags : function( elem ){ console.log( elem );} } } } var el = new Element(); el.getTags(); |
к моменту выполнения кода внутри функции Element() у создаваемого объекта уже установлен старый прототип. Закомментированный код добавляет функцию в этот прототип, а нерабочий вариант просто заменяет Element.prototype, что никак не сказывается на прототипе объекта - он остается прежним.
|
Cпасибо! звучит логично, но вот в книге Фленагана, алгоритм создания
нового объекта, как-то не похож: Для создания экземпляров Person используется оператор new. В результате выполняются четыре действия: 1. Создание объекта. 2. Назначение нового объекта переменной t h i s конструктора (после чего t h i s указывает н а новый объект). 3. Выполнение кода внутри конструктора (добавление свойств к новому объекту). 4. Возвращение нового объекта. Пытаюсь сопоставить ваш ответ с этим алгоритмом и напрашивается только один ответ: ссылка на прототип объекта возвращается вновь созданному объекту раньше чем происходит его инициализация! Пожалуйста дайте ссылку на материал, где можно это уточнить. Дело в том что пункты 3 и 4 очень уж смущают |
Ну в этом алгоритме про прототипы ничего не вижу.
|
мне кажется или когда Element работает в режиме конструктора код ТС просто игнорируется? Я имею в виду что если исполнить снаружи функции, код меняющий прототип, то работать он таки будет.
|
function Element(){ if( typeof Element.getTags !== "function"){ //Element.prototype.getTags = function( elem ){ console.log( elem );} Element.prototype = { constructor: Element, getTags : function( elem ){ console.log( elem );} } } } Element(); // или просто вызвать ее как обычную функцию, чтобы записать прототип var el = new Element(); el.getTags(); Уже размышляю насчет поспать, так что не проверял как это работает, все это просто мои мысли из разряда "а что если..." . Всем неспящим до завтра ;) |
Проверил, и правда так работает. Видимо конструктор работает в особом режиме, в котором код ТС игнорируется. Я вроде где-то про это читал (про особый режим работы конструкторов), не помню где только.
|
Что такое код TC, что-то не могу расшифровать абривиатуру?
Мне кажется не то чтобы код игнорировался просто: получается что когда выполняется строчка var el = new Element(); первым делом объект var el получает ссылку на прототип, а уже потом запускается алгоритм Фланагана?... И инфу не могу найти. Может чего не дочитал еще... Товарищи делитесь соображениями. |
ТС - topic starter.
var el - это переменная, тобишь именованная область памяти, куда мы записываем данные - это не сам объект. Ей присваивается ссылка на уже готовый объект. |
Цитата:
|
прошу прощения алгоритм описывается в книге Николаса Закаса: JavaScript для профессиональных веб-разработчиков.
|
var a = { c:1, a:3 } var b = a; b.c = 0; alert(a.c); Объект существует отдельно от переменных, переменные хранят только ссылку на него, поэтому алерт 0. Из одной переменной мы меняем свойство, а из другой его получаем. Но объект один единственный. |
Точнее, в том первом пункте создаётся пустой объект и ему присваивается прототип. А в переменную el это попадает после 4 пункта
|
Цитата:
|
Цитата:
|
1 {} - создание объекта, свойств нет.
2 this конструктора равен этому обьекту. 3 выполняем код конструктора к примеру this.a = 0 ; в результате наш обьект уже не пуст {a:0}; 4 конструктор завершает работу, и мы наконец передаем ссылку на него в переменную. Както так, незнаю уж насколько понятно изложил. |
Спасибо врубился т.е под созданием объекта (п. 1) подразумевается наполнение его стандартными свойствами javascript в том числе и свойством prototype вместе с его значением на момент создания объекта. А (п. 4) подразумевает просто присвоение переменной el ссылки на
этот объект!? |
Все верно, созданием пустых обьектов занимается специальный конструктор и прототип создает он, еще на этапе номер 1. Потом мы можем его перезаписать.
|
Спасибо aklis,
Яростный Меч! Вы мне очень помогли. |
Ой, ссори поспешил. Все равно не пойму: Вот я
1. создал объект 2. дал ему ссылку на прототип 3. выполнил код внутри функции Element которая перезаписала ссылку на прототип, причем до обращения к этому объекту извне. 4. вернул ссылку на Element переменной var el Т.е. основной вопрос попрежнему остается почему у меня нет доступа к этому прототипу ? |
Я ж говорю не исполняется код этот в режиме конструктора.
Обратите внимание на сообщение номер 6 этой темы. Строка 11. Если вызвать этот конструктор как обычную функцию, до того как используем Element как конструктор, тогда все сработает. Но в режиме конструктора весь ваш код из Element игнорируется. Честно говоря Element вообще не конструктор, она не назначает свойств объекту. |
Кажется понял ответ как всегда на следующей странице):
Хотя свойства и методы, добавленные в прототип, немедленно становятся доступны во всех экземплярах объектов, при перезаписи всего прототипа наблюдается другое поведение. Указатель [[ Prototype ]] задается при вызове конструктора, поэтому изменение прототипа на другой объект нарушает связь между конструктором и оригинальным прототипом. П омните, у экземпляра есть указатель только на прототип, но не на конструктор. Рассмотрим следующий пример: function Person ( ) { } var friend = new Person() ; Person . p rototype = { constructor : Person , name : "Nicholas" , age : 2 9 , job : " Software Engineer " , sayName : function(){ alert ( this.name ) ; } } ; friend.sayName();// ошибка После этого попробовал var el = new Element(); el = new Element(); el.getTags("div"); Теперь понял эту тонкость. что кстати подтверждает 6-е сообщение. Спасибо! |
А нет, попробовал - не игнорируется код. Надо думать тогда.
|
Вот оно что :)
|
Просто получается, что перезапись происходит не у __proto__ который взял ссылку у prototype на момент первого создания
а именно у свойства prototype функции Element. |
Я кстати разницу так до конца и не понял между __proto__ и prototype.
Вроде как __proto__ это конкретно свойство уже существующего объекта, а prototype это свойство конструктора которое влияет на __proto__ в будущем созданных объектов? |
Да я мыслю его также. теперь просто стало понятнее как оно инициализируется.
|
Цитата:
Да уместнее говорить не о prototype конструктора, а о prototype функции Element |
|
Цитата:
|
Цитата:
|
Часовой пояс GMT +3, время: 11:35. |