Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

40 Наследование в JavaScript (Дмитрий Котеров)
Goto page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
Андрей Сумин
Участник форума



Joined: 23 Nov 2005
Posts: 60
Карма: 5
   поощрить/наказать

Location: Москва

PostPosted: Fri Feb 03, 2006 5:59 pm (написано за 2 минуты 2 секунды)
   Post subject:
Reply with quote

А может попробовать не делать ИЗ прототипов наследдование и сделать просто наследование например так:
Code (JavaScript): скопировать код в буфер обмена
function createProp(child, parent, name, arguments){
        return function(){
                return child.parent[name].apply(parent, arguments);
        }
}
function extended(child, parent){
        child.parent = parent;
        var name;
        for (name in parent){
                if (child[name]){continue;}
                if (typeof(parent[name]) == 'function'){
                        child[name] = createProp(child, parent, name, arguments);
                }else{
                        child[name] = parent[name];
                }
        }
}


function One(str){
        this.str = str;
        this.init();
}
One.prototype = {
        init: function(){
                document.writeln('Вызван One.init() - ' + this.str);
        },
        test: function(str){
                document.writeln('Вызван One.test() - ' + str);
        }
}

function Two(str){
        extended(this, new One(str));
        this.init();
}
Two.prototype = {
        init: function(){
                document.writeln('Вызван Two.init() - ' + this.str);
        },
        checkParent: function(str){
                document.writeln('Вызван Two.checkParent() - ' + str);
        }
}

function Tree(str){
        extended(this, new Two(str));
        this.init();
}
Tree.prototype = {
        init: function(){
                document.writeln('Вызван Tree.init() - ' + this.str);
        },
        test: function(str){
                document.writeln('Вызван Tree.test() - ' + str);
                this.parent.test(str);
        }
}

function Four(str){
        extended(this, new Tree(str));
        this.init();
}
Four.prototype = {
        init: function(){
                document.writeln('Вызван Four.init() - ' + this.str);
        }
}


test = new One('one');
test.test('one');
document.writeln(' ================== ');
test = new Two('two');
test.test('two');
document.writeln(' ================== ');
test = new Tree('tree');
test.test('tree');
document.writeln(' ================== ');
test = new Four('four');
test.test('four');
test.checkParent('four');
test.parent.checkParent('four');
Выдаст результат:
Code (any language): скопировать код в буфер обмена
Вызван One.init() - one
Вызван One.test() - one
 ==================
Вызван One.init() - two
Вызван Two.init() - two
Вызван One.test() - two
 ==================
Вызван One.init() - tree
Вызван Two.init() - tree
Вызван Tree.init() - tree
Вызван Tree.test() - tree
Вызван One.test() - tree
 ==================
Вызван One.init() - four
Вызван Two.init() - four
Вызван Tree.init() - four
Вызван Four.init() - four
Вызван Tree.test() - four
Вызван One.test() - four
Вызван Two.checkParent() - four
Вызван Two.checkParent() - four
Back to top
View user's profile Send private message
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 12:19 am (спустя 6 часов 19 минут; написано за 1 минуту 31 секунду)
   Post subject:
Reply with quote

Дмитрий Котеров

На всякий случай, если вы смотрите только обновления топика, я ответил вам развёрнуто на предыдущей странице (просто отредактировал свой же пост)...
Back to top
View user's profile Send private message
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Sat Feb 04, 2006 3:32 am (спустя 3 часа 13 минут; написано за 11 минут 3 секунды)
   Post subject:
Reply with quote

Zeroglif
А всё-таки... Оно работает не так, как Вы описали.
По идее, Ваша теория правильна. Но... практика:
Code (JavaScript): скопировать код в буфер обмена
var A = function() {}
A.prototype.b = 'c'//
var a = new A;
alert(a.b);           //

alert(a.prototype);   //

//
a.prototype = {}      //

a.prototype.b = 'd'//

alert(a.b);           //

a.constructor.prototype.b = 'd'; //

alert(a.b);           //

a.constructor = null;
a.prototype = null;   //

alert(a.b);           //
 
Так что - факт остайтся фактом: поиск идёт по цепочке obj[[Constructor]][[Prototype]]

Дополнение к Вашему примеру:
Code (JavaScript): скопировать код в буфер обмена
  function A() { }; //
  function B() { }; //
       
  b = new B(); //

  A.prototype = B; //
  A.prototype.constructor = null

  a = new A(); //

  alert(a.constructor) // null
  alert(a instanceof A) // true
  alert(a instanceof B) // false
 
Таким образом,
1. Текстовое описание констуктора определяется посредством ссылки obj[[Constructor]][[Prototype]].constructor.
2. Переопределение прототипа не влияет на тип объекта, но изменяет явную цепочку поиска свойств.
Back to top
View user's profile Send private message
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 4:18 am (спустя 45 минут; написано за 10 минут 52 секунды)
   Post subject:
Reply with quote

WingedFox wrote:
Так что - факт остайтся фактом: поиск идёт по цепочке obj[[Constructor]][[Prototype]]
Только пошёл баиньки, а тут... Сразу одна ремарка - под свойством в квадратных скобках мы подразумеваем неявные свойства (согласно ES). Поехали:
Quote:
Code (JavaScript): скопировать код в буфер обмена
var A = function() {}
A.prototype.b = 'c'//
var a = new A;
alert(a.b);           //

alert(a.prototype);   //
 
Этот упс совершенно закономерен, потому что у экземпляра нет явной ссылки к прототипу. Мы можем говорить только о неявной ссылке a.[[Prototype]]. Поэтому a.prototype совершенно корректно отдаст undefined, так же как и a.bar или a.foo, ну нет таких свойств ни в самом экземпляре, ни в его прототипе на момент вашего алерта. Однако сам прототип на законном месте, он может быть как доступен через a.constructor.prototype, так и вообще не доступен (если прибить свойство constructor). Это не важно вовсе.
Quote:
Code (JavaScript): скопировать код в буфер обмена
//
 
Закономерно, само собой.
Quote:
Code (JavaScript): скопировать код в буфер обмена
a.prototype = {}      // ладно, прототип теперь есть.
 
Упаси господи. Ещё раз - явной ссылки нет. Мы не можем изменить прототип после того, как уже экземпляр создан. Мы можем перенаправить ссылку на другой объект у конструктора, но до создания экземпляра. То что вы сейчас сделали - это просто добавили к объекту a самое обыкновенное новое свойство, ведущее к вновь созданному объекту. Эти действия не имеют никакого отношения к прототипу.
Quote:
Code (JavaScript): скопировать код в буфер обмена
a.prototype.b = 'd'//
alert(a.b);           //
a.constructor.prototype.b = 'd'; //
alert(a.b);           //
a.constructor = null;
a.prototype = null;   //
alert(a.b);           //
 
Продолжается та же история, вы снова присваиваете свойства уже новому объекту, это не имеет отношение ни к чему. Что только подтверждается тем, что вы можете легко изменить значение свойства прототипа b, он на месте. Более того, убивая ссылки a.constructor и a.prototype вы просто их убиваете, прототип же как жил, так и продолжает жить, в чём вы сами же и убеждаетесь через alert(a.b). Иными словами все вышеобозначенные действия - это обычная возня со свойствами объекта, она не разрушает связь с прототипом. Единственное, что здесь заслуживает внимания так это свойство a.constructor, вы присвоили ему явно null, теперь вы не сможете взаимодействовать с конструктором/прототипом через a.constructor, т.к. поиск не обратиться к цепочке прототипов, свойство задано явно в поле объекта a.
Quote:
Так что - факт остайтся фактом: поиск идёт по цепочке obj[[Constructor]][[Prototype]]
Абсолютно нет. Никаких фактов. Нет у объекта внутреннего свойства [[Constructor]] (это привилегия функции). Поиск всегда идёт только по неявным ссылкам [[Prototype]][[Prototype]]...
Back to top
View user's profile Send private message
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 4:43 am (спустя 25 минут; написано за 5 минут 48 секунд)
   Post subject:
Reply with quote

WingedFox wrote:
Code (JavaScript): скопировать код в буфер обмена
A.prototype = B; // переопределяем объект-прототип
A.prototype.constructor = null
Обратите внимание, что вы сделали прототипом объект B (функцию), а не экземпляр этой функции b. Второй строкой вы заставили свойство constructor смотреть в null. Результат:
Quote:
Code (JavaScript): скопировать код в буфер обмена
  alert(a.constructor) // null
 
Всё закономерно, интерпретатор ищет свойство в самом объекте a (не находит), потом в объекте B (находит).
Quote:
Code (JavaScript): скопировать код в буфер обмена
alert(a instanceof A) // true
 
Всё закономерно. В цепи прототипов a есть объект, на который ссылается A.prototype
Quote:
Code (JavaScript): скопировать код в буфер обмена
  alert(a instanceof B) // false
 
Всё закономерно. В цепи прототипов a нет объекта, на который ссылается B.prototype. Кстати говоря, если бы вы сделали прототипом не B, а его экземпляр b, то последнее выражение выдало бы true. С выводами опять не согласен. Виноват. ;-)
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 10:18 am (спустя 5 часов 34 минуты; написано за 52 секунды)
   Post subject:
Reply with quote

Zeroglif
Давайте без ложной скромности! Что значит - "не претендуете на истину"? Все, о чем Вы решили напомнить - это ведь азбука JS, которой никто не отменял! Теорию, конечно, можно немного подзабыть...
Кстати, у Вас маленькая описка:
Quote:
Всё закономерно, интерпретатор ищет свойство в самом объекте a (не находит), потом в объекте B (находит).
Ничего он не найдет в объекте B в данном случае...
Back to top
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 10:48 am (спустя 29 минут; написано за 4 минуты 51 секунду)
   Post subject:
Reply with quote

Гость wrote:
Zeroglif
Давайте без ложной скромности! Что значит - "не претендуете на истину"? Все, о чем Вы решили напомнить - это ведь азбука JS, которой никто не отменял!
Не уловил подтекст сказанного. Я что-то не так сделал/делаю?
Гость wrote:
Ничего он не найдет в объекте B в данном случае...
Там null, а может лежать и не null, не важно, что именно, важен принцип поиска...
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 11:00 am (спустя 12 минут; написано за 2 минуты 33 секунды)
   Post subject:
Reply with quote

Zeroglif
Понимание JS Вам дается значительно легче! Жаль, что Вы сразу меня не поняли... Я лишь хотел сказать, что Вы правы, как никто другой. И вообще, Наблу 40 должны были писать именно Вы! Спасибо за внимание.
Back to top
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Sat Feb 04, 2006 2:34 pm (спустя 3 часа 33 минуты; написано за 11 минут 43 секунды)
   Post subject:
Reply with quote

Zeroglif
Всё это прекрасно и замечательно. Но давайте-таки отделим мух от котлет.
Теория, как бы она ни была прекрасна, имеет мало общего с реальностью, если не имеет прямого подтверждения на практике. Что мы и имеем в данном случае.
Ваши знания - это Ваше достояние. Отлично, что Вы точно знаете, как работает движек JS.
Для подтверждения Вашей теории можете приводить цитаты из стандарта, исходные коды JS машины. Но набла объясняет отнюдь не теорию, а практику наследования.

И я ещё раз говорю:
WingedFox wrote:
Но... практика:
Для построения логично работающей системы наследования совершенно не важно КАК работают внутренности движка. Важны именно следствия.
Как в данном случае: без разницы, что именно происходит внутри JS машины при инициализации объекта:
Code (JavaScript): скопировать код в буфер обмена
var A = function() {}
A.prototype.b = 'c'// обозначили переменную в прототипе конструктора.
var a = new A;
Значительно важнее следующее:
Code (JavaScript): скопировать код в буфер обмена
alert(a.prototype);   // упс... а прототипа-то и нет.

a.constructor.prototype.b = 'd'; // а вот так...
alert(a.b);           // всё работает, как и ожидается
 
Что подтверждает явную доступность свойств родительского класса по ссылке obj.constructor.prototype, а не obj.prototype

А раз оно работает именно так, то для практического применения это и есть истина.

Ещё раз - давайте-таки отделим мух от котлет и теорию от практики.
Наблы написаны для того, чтобы показать практическое применение методик.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 5:51 pm (спустя 3 часа 17 минут; написано за 3 минуты 33 секунды)
   Post subject:
Reply with quote

Гость wrote:
И вообще, Наблу 40 должны были писать именно Вы
Камень в мой огород. И при том совершенно справедливый.

Кстати, а есть ли какая-то книга, в которой все это описывается настолько же подробно? Лично я все, что видел под JS, было просто-таки на порядок ниже уровнем.
Zeroglif wrote:
function A() {}; //первый конструктор
function B() {}; //второй конструктор
       
b = new B(); // создаём объект-экземпляр с помощью B;

A.prototype = b; // переопределяем объект-прототип

a = new A(); // создаём объект-экземпляр с помощью A;

alert(a.constructor) // function B() {}
 
Почему же так получается, что a.constructor ведёт к объекту-конструктору B, а не ведёт к создавшему его A. Bсё просто. Интерпретатор не находит этого свойства непосредственно в a (его там нет и не было) и обращается к цепочке прототипов. Объектом-прототипом для a является b, т.к. именно на этот объект ссылалось свойство A.prototype в момент создания a (как я уже говорил раньше, неявное свойство a.[[Prototype]] в момент создания должно вести туда же, к b). Но и в этом объекте интерпретатор не находит свойство constructor и обращается к уже его собственному объекту-прототипу b, то есть объекту-прототипу, ассоциированному с его объектом-конструктором B. Иначе говоря:

/*
  a.constructor - ищем свойство, не находим;
  a.[[Prototype]].constructor - не находим в прототипе, продолжаем искать в прототипе прототипа
  a.[[Prototype]].[[Prototype]].constructor - упс, нашлось, это B
*/
Давайте еще раз остановимся на этом примере. Вы говорите, что свойство constructor появляется НЕ У ЛЮБОГО объекта, созданного по new?
Zeroglif wrote:
Но на этом интерпретатор ещё не закончит свою работу, он автоматом начинает создавать ассоциированный с объектом-конструктором объект-прототип:
- создаётся новый объект;
- значением свойства constructor этого объекта становится создавший его объект-конструктор;
- значением свойства prototype объекта-конструктора становится вновь созданный объект;
Т.е. свойство constructor - это свойство объекта-прототипа, а вовсе даже не объекта-экземпляра?
Back to top
View user's profile Send private message Send e-mail
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 6:21 pm (спустя 30 минут; написано за 1 минуту 42 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров
Quote:
Камень в мой огород. И при том совершенно справедливый.
Весьма приятно убедиться в том, что Вы - интеллигентный человек!
WingedFox
Наследование свойств родительского класса и доступность этих самых свойств с целью их переопределения - две разные задачи. Отсюда и два разных метода соответственно: obj.prototype и obj.constructor.prototype. Подобные задачи были поставлены и успешно решены в обсуждаемой набле. Zeroglif этого не оспаривает, как и не оспаривает практической пользы наблы, он лишь указал на некоторые неточности, которые действительно имеют место быть:
Quote:
прототипы объектов доступны по цепочке:
obj.constructor.prototype.constructor.prototype..., а не obj.prototype.prototype
И уважаемый автор, видимо, с ним согласен...
Zeroglif
Незнаю, поощрили ли Вас оппоненты, но лично я в очередной раз извлек из обсуждения много полезного (+1). И напрасно Вы себя называете "чукчей" ;-)!
Back to top
View user's profile Send private message Send e-mail
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 6:26 pm (спустя 4 минуты)
   Post subject:
Reply with quote

WingedFox wrote:
Для построения логично работающей системы наследования совершенно не важно КАК работают внутренности движка. Важны именно следствия. Как в данном случае: без разницы, что именно происходит внутри JS машины при инициализации объекта
Я как в том ералаше могу только сказать: "У меня нет слов!" или в переводе на современный: "LOL LOL LOL". Тем не менее, вряд ли нам стоит запускать holy war "теория vs. практика" в теме обсуждения набл (ОК?). Давайте лучше вернёмся к теме, к вашему последнему посту по сути. Имеете чего-то против, если я назову полной ерундой (и с практической и с теоретической точки зрения) ;-) нижеследующие ваши слова:
Quote:
a.prototype = {} // ладно, прототип теперь есть.
Quote:
поиск идёт по цепочке obj[[Constructor]][[Prototype]]
Quote:
Текстовое описание констуктора определяется посредством ссылки obj[[Constructor]][[Prototype]].constructor.
и нижеследующие уже не ваши слова:
Quote:
Так вот, после создания объекта интерпретатор присваивает его свойству constructor значение, равное величине, стоящей справа от оператора new.
Quote:
Итак, вывод: прототипы объектов доступны по цепочке obj.constructor.prototype.constructor.prototype
???
Back to top
View user's profile Send private message
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 7:01 pm (спустя 35 минут; написано за 13 минут 33 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Камень в мой огород. И при том совершенно справедливый.
Ни в коем случае, это не камень, это процесс взамного обогащения знаниями.
Дмитрий Котеров wrote:
Давайте еще раз остановимся на этом примере. Вы говорите, что свойство constructor появляется НЕ У ЛЮБОГО объекта, созданного по new?
Именно так, это обыкновенное свойство объекта-прототипа, ссылка на создавший его конструктор.
Quote:
Т.е. свойство constructor - это свойство объекта-прототипа, а вовсе даже не объекта-экземпляра?
Согласно Ecma-262 именно так.
Дмитрий Котеров wrote:
Кстати, а есть ли какая-то книга, в которой все это описывается настолько же подробно? Лично я все, что видел под JS, было просто-таки на порядок ниже уровнем.
Идеала, увы, не встречал. Очень удачной по сути и по удобству пользования (.chm) считаю фланагановский DG (JavaScript.The.Definitive.Guide.4th.Edition.by.David.Flanagan(O'Reilly.2001)), недавно попалась свежая Wrox.Professional.JavaScript.For.Web.Developers.Apr.2005.eBook-DDU.pdf, там выведены условные парадигмы наследования. А вообще говоря, у меня такое ощущение, что очень толковые книги должны быть по ActiveScript, во всяком случае некоторые туториалы меня поразили профессиональным подходом. Никогда не читал, а надо бы. К сожалению, так уж сложилось, что несчастная история развития J(ava)Script вывела в свет огромное количество книг ни о чём, читать просто нечего...
Back to top
View user's profile Send private message
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Sat Feb 04, 2006 7:38 pm (спустя 37 минут; написано за 2 минуты 14 секунд)
   Post subject:
Reply with quote

Zeroglif
В общем - да. Согласен.
Back to top
View user's profile Send private message
bæv
Модератор «Дзена»



Joined: 27 Aug 2003
Posts: 7275
Карма: 9986
   поощрить/наказать


PostPosted: Sat Feb 04, 2006 11:43 pm (спустя 4 часа 4 минуты; написано за 1 минуту 7 секунд)
   Post subject:
Reply with quote

Zeroglif wrote:
Wrox.Professional.JavaScript.For.Web.Developers.Apr.2005.eBook-DDU.pdf
Я б прямую ссылку дал...
В общем, чтоб правила не нарушать, строка для поиска в рунете:
Wrox Professional JavaScript For Web Developers Apr 2005 ISBN0764579088 pdf
Back to top
View user's profile Send private message
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 11:05 am (спустя 11 часов 21 минуту; написано за 1 минуту 24 секунды)
   Post subject:
Reply with quote

Zeroglif
Скажите, по прежнему можно считать, что значением св-ва constructor является ссылка на объект-конструктор?
Back to top
View user's profile Send private message Send e-mail
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 1:05 pm (спустя 2 часа 3 секунды; написано за 7 минут 8 секунд)
   Post subject:
Reply with quote

AKS wrote:
Скажите, по прежнему можно считать, что значением св-ва constructor является ссылка на объект-конструктор?
Почему по-прежнему? Расскажите, что смущает - я попробую прояснить.
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 2:35 pm (спустя 1 час 30 минут; написано за 1 минуту 48 секунд)
   Post subject:
Reply with quote

Zeroglif
Дело в том, что описывать действия интерпретатора, как поиск св-ва constructor, наверное не совсем верно. Св-во constructor хранит ссылку от прототипа к конструктору, значит поиск будет иметь целью найти конструктор, пробежав через цепь прототипов, если таковая имеется, а не поиск пресловутого св-ва constructor.
Back to top
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 2:40 pm (спустя 5 минут; написано за 40 секунд)
   Post subject:
Reply with quote

Zeroglif
Это я высказался от имени гостя, забыв авторизоваться...
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 2:41 pm (спустя 51 секунду)
   Post subject:
Reply with quote

Zeroglif wrote:
Т.е. свойство constructor - это свойство объекта-прототипа, а вовсе даже не объекта-экземпляра?
Согласно Ecma-262 именно так.
Блин, ну это же совершенно не логично. И куда смотрели авторы JavaScript, когда такое удумали? :-)
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 2:59 pm (спустя 17 минут; написано за 4 минуты 4 секунды)
   Post subject:
Reply with quote

Короче говоря, чтобы пример работал так, как от него и ожидается из соображений наблы, надо писать так:
Code (JavaScript): скопировать код в буфер обмена
function B() {} //
function A() {} //
       
b = new B(); //

A.prototype = b;    //

a = new A(); //
a.constructor = A;

alert(a.constructor) // function A() {}
alert(a.constructor.prototype.constructor) // function B() {}
 
Т.е. если мы где-то делаем x = new A(), то надо делать и x.constructor = A.

Правда, это способ плох тем, что создается явное свойство constructor, доступное через тот же foreach. Увы, одним лишь манипулированием A.prototype обойтись не выйдет никак.
Back to top
View user's profile Send private message Send e-mail
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 3:52 pm (спустя 52 минуты; написано за 1 минуту 45 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров
Да не надо пытаться переопределить конструктор прототипа:
Quote:
a.constructor = A;
Достаточно так:
Quote:
function B() {} // базовый конструктор
function A() {} // производный конструктор

b = new B(); // создаём объект-экземпляр с помощью B

a = new A(); // создаём объект-экземпляр с помощью A;

A.prototype = b; // переопределяем объект-прототип

alert(a.constructor) // function A() {}
alert(a.constructor.prototype.constructor) // function B() {}
Свойсто constructor существует для того, чтобы хранить ссылку на объект-конструктор. В этом вся логика и это и было задумано разработчиками JS.
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 4:21 pm (спустя 29 минут; написано за 1 минуту 52 секунды)
   Post subject:
Reply with quote

AKS wrote:
a = new A(); // создаём объект-экземпляр с помощью A;
A.prototype = b; // переопределяем объект-прототип
К сожалению, такой способ не подходит, т.к. мы не знаем, не будут ли в дальнейшем создаваться другие объекты с конктруктором A. Очевидно, присваивание A.prototype нужно делать ПОСЛЕ того, как созданы ВСЕ объекты new A(), иначе получаем предыдущую проблему.

Впрочем, на время вызова new A() можно устанавливать в null A.prototype, а затем - его восстанавливать обратно. Наверное, так тоже сработает.
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 4:24 pm (спустя 2 минуты; написано за 49 секунд)
   Post subject:
Reply with quote

Да, вот так работает:
Code (JavaScript): скопировать код в буфер обмена
function B() {} // базовый конструктор
function A() {} // производный конструктор

b = new B(); // создаём объект-экземпляр с помощью B
A.prototype = b;

var sv = A.prototype;
delete A.prototype;
a = new A(); // создаём объект-экземпляр с помощью A;
A.prototype = sv;

alert(a.constructor) // function A() {}
alert(a.constructor.prototype.constructor) // function B() {}
 
Примечательно, что A.prototype=null не срабатывает, надо делать именно delete.
Back to top
View user's profile Send private message Send e-mail
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 5:57 pm (спустя 1 час 33 минуты; написано за 7 минут 43 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Т.е. если мы где-то делаем x = new A(), то надо делать и x.constructor = A
Вроде этого, зависит от задач, часто можно встретить, как ссылку на конструктор восстанавливают по кругу:
Code (JavaScript): скопировать код в буфер обмена
A.prototype.constructor=A
B.prototype.constructor=B
AKS wrote:
Св-во constructor хранит ссылку от прототипа к конструктору, значит поиск будет иметь целью найти конструктор, пробежав через цепь прототипов, если таковая имеется, а не поиск пресловутого св-ва constructor.
Прототип - это самый первый объект "класса", в момент создания этого первого объекта, он автоматически получает свойство constructor, значением которого и является конструктор, его же и создавший. Это в плане доступа к свойству, в плане технологии поиска, ничем не отличается от любого другого свойства прототипа, например, toString (). Отличие в том, что если переопределим сам прототип, то изменится и constructor.
AKS wrote:
Code (JavaScript): скопировать код в буфер обмена
function B() {} // базовый конструктор
function A() {} // производный конструктор

b = new B(); // создаём объект-экземпляр с помощью B

a = new A(); // создаём объект-экземпляр с помощью A;

A.prototype = b; // переопределяем объект-прототип

alert(a.constructor) // function A() {}
alert(a.constructor.prototype.constructor) // function B() {}
 
В этом примере есть важное допущение. Прототип переопределяется уже после создания экземпляра a, значит, для a это изменение ничем не грозит, его прототип стандартный, он не изменился, отсюда:
Code (JavaScript): скопировать код в буфер обмена
alert(a.constructor) // function A() {}
 
Наоборот, этот алерт:
Code (JavaScript): скопировать код в буфер обмена
alert(a.constructor.prototype.constructor) // function B() {}
 
покажет на B, по той простой причине, что A.prototype и a.[[Prototype]] смотрят сейчас на совершенно разные объекты прототипы, то есть alert(a instanceof B) даст false.

А какого результата вы хотите добиться, в принципе, от свойства constructor?
Back to top
View user's profile Send private message
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 7:35 pm (спустя 1 час 37 минут; написано за 12 минут 1 секунду)
   Post subject:
Reply with quote

Дмитрий Котеров

Я в ваш пример комментов добавил.
Code (JavaScript): скопировать код в буфер обмена
function B() {} // конструктор
function A() {} // конструктор

b = new B(); // создаём объект-экземпляр с помощью B
A.prototype = b; // перевели ссылку с родного прототипа на новый объект b

var sv = A.prototype; // сохранили ссылку на новый объект b в переменной
delete A.prototype; // убили ссылку на b (IE), ничего не убили (Gecko)
a = new A(); // создаём объект-экземпляр с помощью A;
/*
Создаётся новый объект, в его внутренне свойство [[Prototype]] нужно подставить значение свойства A.prototype, но там не пойми чего, в зависимости от браузера. Без прототипа жить нельзя по-определению, и при его отстутствии интерпретатор вынужден из-под полы достать ещё один стандартный объект, чтобы свойство [[Prototype]] не пустовало.
*/


A.prototype = sv; // ведущая в никуда ссылка ведёт теперь к [b]b[/b], но это ни на что не влияет

alert(a.constructor) // родная function Object(){} у IE, у Gecko function A(){}
alert(a.constructor.prototype.constructor) // то же самое для IE, у Gecko function B(){}
 
В общем, удалять Конструктор.prototype с помощью оператора delete - браузерозависимая штучка, лучше в null, а ещё лучше вообще не удалять.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 7:59 pm (спустя 24 минуты; написано за 1 минуту 11 секунд)
   Post subject:
Reply with quote

Zeroglif wrote:
А какого результата вы хотите добиться, в принципе, от свойства constructor?
Результата я хочу добиться лишь одного: добиться того, чтобы можно было наследование JavaScript "подогнать" под наследование класс-ориентированных языков (C++, Java и т.д.). Т.е. чтобы можно было использовать JavaScript примерно так же, как в класс-ориентированных языках.

Из Ваших рассуждений следует, что это, вообще говоря, невозможно...
Back to top
View user's profile Send private message Send e-mail
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 8:55 pm (спустя 55 минут; написано за 51 секунду)
   Post subject:
Reply with quote

Zeroglif
Итак, для себя я делаю следующий вывод:
Объект-прототип имеет св-во constructor, значением которого является именно объект-конструктор, но никак не ссылка на объект-конструктор.
Извините, если что, Вы ведь сами меня тут недавно учили вникать в такого рода тонкости...
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 9:39 pm (спустя 44 минуты; написано за 37 секунд)
   Post subject:
Reply with quote

AKS wrote:
значением которого является именно объект-конструктор, но никак не ссылка на объект-конструктор
В JavaScript все - ссылка (за исключением скалярных типов, таких как целое, строка и т.д.). Так что Ваше утверждение, мне кажется, лишено смысла.
Back to top
View user's profile Send private message Send e-mail
Guest






Карма: 388
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 10:14 pm (спустя 34 минуты; написано за 34 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров
Это не мое утверждение. Это мой вывод из рассуждений Zeroglif:
Quote:
Прототип - это самый первый объект "класса", в момент создания этого первого объекта, он автоматически получает свойство constructor, значением которого и является конструктор, его же и создавший.
До этого я писал:
Quote:
Св-во constructor хранит ссылку от прототипа к конструктору, значит поиск будет иметь целью найти конструктор, пробежав через цепь прототипов, если таковая имеется, а не поиск пресловутого св-ва constructor.
Back to top
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 10:16 pm (спустя 2 минуты; написано за 41 секунду)
   Post subject:
Reply with quote

Дмитрий Котеров
Выше - мое сообщение (опять не залогинился)...
Back to top
View user's profile Send private message Send e-mail
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Sun Feb 05, 2006 11:45 pm (спустя 1 час 28 минут)
   Post subject:
Reply with quote

AKS wrote:
Это не мое утверждение. Это мой вывод из рассуждений Zeroglif:
Возможно, я плохо объяснил, попробую ещё раз разобрать ваш пост? еслия правильно его понял:
AKS wrote:
Дело в том, что описывать действия интерпретатора, как поиск св-ва constructor, наверное не совсем верно. Св-во constructor хранит ссылку от прототипа к конструктору, значит поиск будет иметь целью найти конструктор, пробежав через цепь прототипов, если таковая имеется, а не поиск пресловутого св-ва constructor.
А каким ещё путём остаётся описывать действия? Нам нужно обратиться к a.constructor, парсеру до балды, что там лежит, ему прежде всего надо проверить наличие свойства с именем constructor у объекта a. Если он не находит, то обращается к прототипу a и так далее, но обращения к цепи прототипов не будет, если свойство с таким именем будет сразу найдено в самом объекте a. В этом смысле имеет место не поиск с целью найти конструктор, а поиск с целью отыскать "владельца" свойства с определённым именем, чтобы получить его (свойства) значение. Под значением (value) само собой подразумевается или reference-value (если объект), или primitive-value (если число и проч), или string. Всё зависит от того, осталось ли свойство constructor нетронутым (объект) или его забили ерундой...
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Mon Feb 06, 2006 9:08 am (спустя 9 часов 23 минуты; написано за 7 минут)
   Post subject:
Reply with quote

Дмитрий Котеров
Есть небольшая функция добавлающая (местами изменяющая) поведение объекта Array (уже созданного):
Code (JavaScript): скопировать код в буфер обмена
function HArray(keys, array){
    // private:
    var order=null;
    var direct=0;
    // compare
    var cmp=function (a,b){
        for (var key in order)
            if( a[key] != b[key] )
                return (a[key] > b[key] ? order[key] : - order[key])
                        ^ (array.lockRevers[key] || direct)
        return 0
    }
    // public:
    // add() - the convert a arr subarrays to hashes and add to array
    array.add=function(arr){
        for(var i=0, l=array==arr?0:array.length; arr[i]; i++, l++){
            var j=0, hash={};
            for(var k in keys) hash[k]=arr[i][j++];
            array[l]=hash
        }
    }
    array.sort=function(ord){
        ord && (order=ord);
        this.native_sort(cmp)
    }
    array.lockRevers={};
    array.swapDirection=function(){direct^=-2}
    array.clearDirection=function(){direct=0}
    array.native_sort=Array.prototype.sort;
    // default sortings:
    for(var k in keys) (function(s){ array.sort[k]=function(){ array.sort(s) } })(keys[k])
    // init: the convert the array subarrays to hashes
    array.add(array)
    //*/
    return array
}
Хотелось бы переписать эту фун-ю в конструктор соответствующего класса, но возникают проблемы с инициалицацией массива конструктором при создании объекта. Существует ли возможность создать объект наследующий у Array так чтобы можно было инициализировать его подобно:
Code (JavaScript): скопировать код в буфер обмена
my_array = new MyArray ("value 1", "value 2", "value 3")
?
Back to top
Denis Usenko
Участник форума



Joined: 06 Feb 2006
Posts: 54
Карма: 13
   поощрить/наказать


PostPosted: Mon Feb 06, 2006 9:19 am (спустя 10 минут; написано за 1 минуту 17 секунд)
   Post subject:
Reply with quote

Пост выше - мой (был зарегистрирован как DenVdmj, но не постил, и похоже аккаунт теперь удален в связи последними изменениями :))
Back to top
View user's profile Send private message
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Mon Feb 06, 2006 10:43 am (спустя 1 час 24 минуты; написано за 16 секунд)
   Post subject:
Reply with quote

Zeroglif
Все, спасибо, этот вопрос теперь исчерпан!
Back to top
View user's profile Send private message Send e-mail
Андрей Сумин
Участник форума



Joined: 23 Nov 2005
Posts: 60
Карма: 5
   поощрить/наказать

Location: Москва

PostPosted: Mon Feb 06, 2006 11:45 am (спустя 1 час 2 минуты; написано за 2 минуты 37 секунд)
   Post subject:
Reply with quote

Zeroglif.
Итак меня тоже волнует вопрос заданный Дмитрием.
Дмитрий Котеров wrote:
Результата я хочу добиться лишь одного: добиться того, чтобы можно было наследование JavaScript "подогнать" под наследование класс-ориентированных языков (C++, Java и т.д.). Т.е. чтобы можно было использовать JavaScript примерно так же, как в класс-ориентированных языках.

Из Ваших рассуждений следует, что это, вообще говоря, невозможно...
Стоит ли пробовать организовать наследование из прототипов или оставить их в покое пусть выполняют свою прямую функцию?
Back to top
View user's profile Send private message
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Mon Feb 06, 2006 3:21 pm (спустя 3 часа 35 минут; написано за 2 минуты 26 секунд)
   Post subject:
Reply with quote

Андрей Сумин wrote:
Итак меня тоже волнует вопрос заданный Дмитрием.
Боюсь, я не возмусь за такую сложную задачу, как прямое сравнение с С++ и проч., не способен...
Андрей Сумин wrote:
Стоит ли пробовать организовать наследование из прототипов или оставить их в покое пусть выполняют свою прямую функцию?
Конечно стоит, для того и написано чёрным по-белому "Each constructor has a Prototype property that is used to implement prototype-based inheritance and shared properties". Если есть возможность использовать - надо использовать.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Mon Feb 06, 2006 3:32 pm (спустя 11 минут; написано за 57 секунд)
   Post subject:
Reply with quote

Мало ведь проэмулировать наследование в стиле C++ - это как раз довольно легко, можно при создании объекта явно копировать в его пустой прототип члены базовых "классов-объектов". Хотелось бы еще, чтобы работал оператор instanceof, typeof и т.д.
Back to top
View user's profile Send private message Send e-mail
Андрей Сумин
Участник форума



Joined: 23 Nov 2005
Posts: 60
Карма: 5
   поощрить/наказать

Location: Москва

PostPosted: Mon Feb 06, 2006 4:18 pm (спустя 45 минут; написано за 1 минуту 44 секунды)
   Post subject:
Reply with quote

Zeroglif wrote:
Конечно стоит, для того и написано чёрным по-белому "Each constructor has a Prototype property that is used to implement prototype-based inheritance and shared properties". Если есть возможность использовать - надо использовать.
Ну что будем копать. Хотя приведенный мной вариант реализации наследования пока меня устраивает хочется чего-то более "глубокого" чтоли.
Back to top
View user's profile Send private message
AKS
Участник форума



Joined: 28 Dec 2005
Posts: 1174
Карма: 102
   поощрить/наказать


PostPosted: Sun Feb 19, 2006 5:07 pm (спустя 13 дней 48 минут; написано за 33 секунды)
   Post subject:
Reply with quote

А работает ли метод isPrototypeOf()? Кто-нибудь знает?
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Goto page Previous  1, 2, 3, 4, 5, 6  Next
Page 2 of 6    Email to a Friend.
Post a reply
Username
Subject
Господа спамеры и оптимизаторы!

Вы можете даже и не пытаться вставлять в текст поста ссылки - они все равно автоматически удаляются (вернее, тэги <a> заменяются на тэги <u>).

Но если не поверите и все же попытаетесь - как только увидите, что все безрезультатно, удалите свой пост, пожалуйста. Модераторы тоже люди, нехорошо, если они погрязнут в тоннах спама.
     

Disable BBCode in this post
Disable Smilies in this post
    HTML is OFF
BBCode is ON
Smilies are ON
You cannot post new topics in this forum. You can reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML