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

40 Наследование в JavaScript (Дмитрий Котеров)
Goto page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
anycat
Guest





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


PostPosted: Sat Feb 25, 2006 7:10 am (написано за 6 минут 32 секунды)
   Post subject:
Reply with quote

Читал, много думал, неужели все НАСТОЛЬКО жестко
Дмитрий Котеров wrote:
Результата я хочу добиться лишь одного: добиться того, чтобы можно было наследование JavaScript "подогнать" под наследование класс-ориентированных языков (C++, Java и т.д.). Т.е. чтобы можно было использовать JavaScript примерно так же, как в класс-ориентированных языках.
Из Client Reference JS 1.3:
Quote:
You can use call to chain constructors for an object, similar to Java.
попробовал - получилось еще и множественное наследование... никаких constructor и prototype. Что не так?
Code (JavaScript): скопировать код в буфер обмена
// базовый объект
function Vehicle(name) {
    this.name = name;
    document.writeln('<br>Вызван конструктор Vehicle: ' + this.name);
   
    this.drive = function() {
        document.writeln('<br>Вызван Vehicle.drive(): ' + this.name);
    }
   
    this.crack = function() {
        document.writeln('<br>Вызван Vehicle.crack(): ' + this.name);
    }
   
    // private property
    var code;
   
    this.setCode = function(cd) {
        code = cd;
    }
   
    this.code = function(cd) {
        document.writeln('<br>Вызван Vehicle.code(): ' + code);
    }
   
    // private method
    function dumdum() {
        return 'Vehicle.dumdum()';
    }
   
    this.showPrivate = function() {
        document.writeln('<br>Вызван private method: ' + dumdum());
    }
}

// Кар - производный объект от Vehicle - добавлен тип топлива fuel
function Car(name, fuel) {
    Vehicle.call(this, name); // вызываем конструктор родителя
    this.fuel = fuel;
    document.writeln('<br>Вызван конструктор Car: ' + this.name + ' [' + this.fuel + ']');
   
    // переопределяем родительский drive, crack не трогаем
    this.drive = function() {
        document.writeln('<br>Вызван Car.drive(): ' + this.name + ' [' + this.fuel + ']');
    }
}

// Автобус - производный объект от Car - добавлено к-во мест seat
function Bus(name, fuel, seat) {
    Car.call(this, name, fuel); // вызываем конструктор родителя
    this.seat = seat;
    document.writeln('<br>Вызван конструктор Bus: ' + this.name + ' [' + this.fuel + '] [' + this.seat + ']');
}

// Кот
function Cat(name) {
    this.name = name;
    document.writeln('<br>Вызван конструктор Cat: ' + this.name);
   
    this.mew = function() {
        document.writeln('<br>Вызван Cat.mew(): ' + this.name);
    }
}

// скрещиваем кота с автобусом - множественное наследование
function BusCat(name, fuel, seat) {
    Bus.call(this, name, fuel, seat); // вызываем конструктор родителя
    Cat.call(this, name); // вызываем конструктор второго родителя
}

// стартуем...
document.writeln('Program started');
document.writeln('<br><br>Vehicle:');
var tlg = new Vehicle('Телега');
tlg.drive();
tlg.crack();
document.writeln('<br><br>Car:');
var zp = new Car('Запорожец', 'бензин');
zp.drive();
zp.crack();
document.writeln('<br>----------------');
var kz = new Car('Камаз', 'дизель');
kz.drive();
kz.crack();
zp.drive();
document.writeln('<br><br>Bus:');
var gz = new Bus('Газель', 'бензин', 10);
gz.drive();
gz.crack();
document.writeln('<br><br>Cat:');
var bgm = new Cat('Бегемот');
bgm.mew();

document.writeln('<br><br>BusCat (множественное наследование):');
var bgm = new BusCat('Бегемот', 'керосин', 16);
bgm.drive();
bgm.crack();
bgm.mew();
bgm.setCode(12345);
bgm.code();
bgm.showPrivate();
получаем:
Program started

Vehicle:
Вызван конструктор Vehicle: Телега
Вызван Vehicle.drive(): Телега
Вызван Vehicle.crack(): Телега

Car:
Вызван конструктор Vehicle: Запорожец
Вызван конструктор Car: Запорожец [бензин]
Вызван Car.drive(): Запорожец [бензин]
Вызван Vehicle.crack(): Запорожец
----------------
Вызван конструктор Vehicle: Камаз
Вызван конструктор Car: Камаз [дизель]
Вызван Car.drive(): Камаз [дизель]
Вызван Vehicle.crack(): Камаз
Вызван Car.drive(): Запорожец [бензин]

Bus:
Вызван конструктор Vehicle: Газель
Вызван конструктор Car: Газель [бензин]
Вызван конструктор Bus: Газель [бензин] [10]
Вызван Car.drive(): Газель [бензин]
Вызван Vehicle.crack(): Газель

Cat:
Вызван конструктор Cat: Бегемот
Вызван Cat.mew(): Бегемот

BusCat (множественное наследование):
Вызван конструктор Vehicle: Бегемот
Вызван конструктор Car: Бегемот [керосин]
Вызван конструктор Bus: Бегемот [керосин] [16]
Вызван конструктор Cat: Бегемот
Вызван Car.drive(): Бегемот [керосин]
Вызван Vehicle.crack(): Бегемот
Вызван Cat.mew(): Бегемот
Вызван Vehicle.code(): 12345
Вызван private method: Vehicle.dumdum()
Back to top
AKS
Участник форума



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


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

anycat
Да все так! Вот здесь можно глянуть на современный подход к наследованию www.nczonline.net/downloads/(чуть выше Zeroglif подсказал почитать этого автора...)
Back to top
View user's profile Send private message Send e-mail
anycat
Guest





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


PostPosted: Wed Mar 01, 2006 1:12 am (спустя 2 дня 16 часов 50 минут; написано за 1 минуту 24 секунды)
   Post subject:
Reply with quote

AKS
Спасибо за наводку! Конечно проблема вызова методов суперкласса так просто не решается.. хотя тоже решается )
Back to top
AKS
Участник форума



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


PostPosted: Wed Mar 01, 2006 9:19 am (спустя 8 часов 7 минут; написано за 16 секунд)
   Post subject:
Reply with quote

anycat
В любом случае - неплохая информация к размышлению, так ведь?
Back to top
View user's profile Send private message Send e-mail
spat
Заглянувший



Joined: 17 May 2006
Posts: 8
Карма: 0
   поощрить/наказать


PostPosted: Wed May 17, 2006 10:16 am (спустя 2 месяца 16 дней 57 минут; написано за 5 минут 11 секунд)
   Post subject:
Reply with quote

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

Следующий код не даёт ожидаемого результата в IE6:
Code (JavaScript): скопировать код в буфер обмена
        var classA = newClass(
                null,
                {
                        toString: function() { return "classA"; }
                }
        );
        alert(new classA());
Вместо "classA" выдаёт "[object Object]".
В то время как такой пример под IE6 даёт правильный результат:
Code (JavaScript): скопировать код в буфер обмена
        var classA = function() {};
        classA.prototype.toString = function() { return "classA"; };
        alert(new classA());
Можете ли Вы исправить newClass()?
Back to top
View user's profile Send private message
spat
Заглянувший



Joined: 17 May 2006
Posts: 8
Карма: 0
   поощрить/наказать


PostPosted: Wed May 17, 2006 10:23 am (спустя 7 минут; написано за 1 минуту 36 секунд)
   Post subject:
Reply with quote

Кстати, понятно почему так происходит. Потому что тупой IE при переборе свойств объекта пропускает toString, а может и ещё что-нибудь пропускает:
Code (JavaScript): скопировать код в буфер обмена
        var x = {};
        x.toString = function() { return "x"; };

        for (var k in x)
        {
                alert(k);
        }
Back to top
View user's profile Send private message
spat
Заглянувший



Joined: 17 May 2006
Posts: 8
Карма: 0
   поощрить/наказать


PostPosted: Wed May 17, 2006 10:31 am (спустя 7 минут; написано за 2 минуты 4 секунды)
   Post subject:
Reply with quote

Такое решение работает
Code (JavaScript): скопировать код в буфер обмена
function newClass(parent, prop)
{
        // Dynamically create class constructor.
        var clazz = function()
        {
                // Stupid JS need exactly one "operator new" calling for parent
                // constructor just after class definition.
                if (clazz.preparing)
                {
                        return delete(clazz.preparing);
                }
                // Call custom constructor.
                if (clazz.constr)
                {
                        this.constructor = clazz; // we need it!
                        clazz.constr.apply(this, arguments);
                }
        }
        clazz.prototype = {}; // no prototype by default
        if (parent)
        {
                parent.preparing = true;
                clazz.prototype = new parent;
                clazz.prototype.constructor = parent;
                clazz.constr = parent; // BY DEFAULT - parent constructor
        }
        if (prop)
        {
                var cname = "constructor";
                for (var k in prop)
                {
                        if (k != cname)
                        {
                                clazz.prototype[k] = prop[k];
                        }
                }
                if (prop[cname] && prop[cname] != Object)
                {
                              clazz.constr = prop[cname];
                }
                clazz.prototype.toString = prop.toString;
        }
        return clazz;
}
Правда в таком примере поведение всё же неправильное:
Code (JavaScript): скопировать код в буфер обмена
        var classA = newClass(null,
                {
                        toString: function()
                        {
                                return "classA";
                        }
                }
        );

        var classB = newClass(classA, {});

        alert(new classB());
Выдаёт "[obejct Object]" вместо ожидаемого "classA".
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Wed May 17, 2006 1:06 pm (спустя 2 часа 34 минуты)
   Post subject:
Reply with quote

spat
А при создании экземпляра classB вроде бы не вызывается метод, возвращающий строку "classA"...
Back to top
View user's profile Send private message Send e-mail
spat
Заглянувший



Joined: 17 May 2006
Posts: 8
Карма: 0
   поощрить/наказать


PostPosted: Fri May 19, 2006 5:45 pm (спустя 2 дня 4 часа 38 минут; написано за 2 минуты 44 секунды)
   Post subject:
Reply with quote

Функция alert() преобразует аргумент к строке, так что написав alert(new classB()),
мы должны получить в окошке alert-а текст - результат выполнения (new classB()).toString()
Но это не суть важно.
Back to top
View user's profile Send private message
spat
Заглянувший



Joined: 17 May 2006
Posts: 8
Карма: 0
   поощрить/наказать


PostPosted: Fri May 19, 2006 5:58 pm (спустя 13 минут; написано за 6 минут 17 секунд)
   Post subject:
Reply with quote

Вот ещё один интересный пример.
Code (JavaScript): скопировать код в буфер обмена
var classA = newClass
(
        null,
        {
                constructor: function()
                {
                },
                toString: function()
                {
                        return "classA";
                }
        }
);
var classB = newClass
(
        classA,
        {
                constructor: function()
                {
                        this.constructor.prototype.constructor.call(this); // то же, что и classA.call(this);
                },
                toString: function()
                {
                        return "classB";
                }
        }
);

var objA = new classA();
var objB = new classB();

document.writeln("objA.toString() = " + objA);
document.writeln("objB.toString() = " + objB);
document.writeln("------------------------");
document.writeln("objA instanceof classA = " + (objA instanceof classA));
document.writeln("objA instanceof classB = " + (objA instanceof classB));
document.writeln("objB instanceof classA = " + (objB instanceof classA));
document.writeln("objB instanceof classB = " + (objB instanceof classB));
В Firefox 1.5 всё как и должно быть:
Code (any language): скопировать код в буфер обмена
objA.toString() = classA
objB.toString() = classB
------------------------
objA instanceof classA = true
objA instanceof classB = false
objB instanceof classA = true
objB instanceof classB = true
Однако, в браузере Firefox версии 1.0.7 и ниже наблюдается интересная ситуация.
После вызова конструктора оба объекта становятся "экземплярами" обоих "классов", судя по instanceof:
Code (any language): скопировать код в буфер обмена
objA.toString() = classA
objB.toString() = classB
------------------------
objA instanceof classA = true
objA instanceof classB = true
objB instanceof classA = true
objB instanceof classB = true
Дзен.
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Fri May 19, 2006 6:52 pm (спустя 53 минуты; написано за 2 минуты 26 секунд)
   Post subject:
Reply with quote

spat
Тут не Дзен, а что-то другое, но дело темное - лучше не соваться...
По поводу строки "classA" я же не зря написал, что метод, её возвращающий, вызван не был. Чтобы наконец-то увидеть эту строку, пишите:
Code (any language): скопировать код в буфер обмена
var classB = newClass(classA, null);

alert(new classB);
Back to top
View user's profile Send private message Send e-mail
Guest






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


PostPosted: Sat May 20, 2006 8:17 am (спустя 13 часов 24 минуты; написано за 3 минуты 20 секунд)
   Post subject:
Reply with quote

В моём примере был вызван метод toString(), взятый от {} (у Object ведь тоже есть toString() в прототипе).
Подставлять null вторым аргументом - частный случай, когда класс при наследовании не расширяется - это не интересно.
Back to top
spat
Заглянувший



Joined: 17 May 2006
Posts: 8
Карма: 0
   поощрить/наказать


PostPosted: Sat May 20, 2006 8:20 am (спустя 3 минуты; написано за 1 минуту 14 секунд)
   Post subject:
Reply with quote

Пост выше - мой :)
На всякий случай напоминаю, что этот пример с модифицированной под toString() версией newClass(), код которой несколькими постами выше.
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Sat May 20, 2006 8:23 am (спустя 2 минуты; написано за 1 минуту 55 секунд)
   Post subject:
Reply with quote

Вот и был получен результат: "[object Object]"
А вообще Вы ведь сами знаете ответы на свои вопросы:
Вы писали:
Quote:
var classA = function() {};
classA.prototype.toString = function() { return "classA"; };
alert(new classA());
- лучше не придумать (как мне кажется)...
Back to top
View user's profile Send private message Send e-mail
spat
Заглянувший



Joined: 17 May 2006
Posts: 8
Карма: 0
   поощрить/наказать


PostPosted: Sat May 20, 2006 8:31 am (спустя 8 минут; написано за 59 секунд)
   Post subject:
Reply with quote

AKS, согласен :) Так-то оно надёжно. Но как было-бы красиво :)
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Sat May 20, 2006 8:34 am (спустя 2 минуты; написано за 2 минуты 6 секунд)
   Post subject:
Reply with quote

spat
Точно, хочется что-нибудь сотворить, и вообще, интересно все это. Однако, поковырявшись, начинаешь задумываться - а где все это может пригодиться по настоящему. И вот на такие вопросы я пока ответа не нахожу.
Back to top
View user's profile Send private message Send e-mail
Chifa
Заглянувший



Joined: 23 May 2006
Posts: 1
Карма: 0
   поощрить/наказать


PostPosted: Tue May 23, 2006 6:37 pm (спустя 3 дня 10 часов 3 минуты; написано за 4 минуты 43 секунды)
   Post subject: нашел еще одну реализацию наследования
Reply with quote

AKS wrote:
anycat
Да все так! Вот здесь можно глянуть на современный подход к наследованию www.nczonline.net/downloads/...
www.nity.ru/static/javascript-inherit-pattern.html - здесь используется тот же принцип, но в другом исполнении. Особенно меня порадовала реализация обращений к методам родительского объекта - красиво!
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Tue May 23, 2006 8:14 pm (спустя 1 час 36 минут; написано за 2 минуты 8 секунд)
   Post subject:
Reply with quote

Chifa
Интересно (!!!никакого подвоха, просто интересно) - можно ли считать недостатком невозможность использования св-ва constructor у создаваемых экземпляров?
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



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


PostPosted: Tue May 23, 2006 9:06 pm (спустя 52 минуты; написано за 32 секунды)
   Post subject:
Reply with quote

Я не понял, у них что, конструкторы родителей автоматически вызываются, что ли? А если надо родительский конструктор с другими параметрами вызвать?
Back to top
View user's profile Send private message Send e-mail
AKS
Участник форума



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


PostPosted: Wed May 24, 2006 7:14 am (спустя 10 часов 7 минут; написано за 47 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров
Quote:
/** Call the constructor of this class if exists */
Видимо, в демонстрационных целях...
Back to top
View user's profile Send private message Send e-mail
Миша Спларов
Участник форума



Joined: 17 Nov 2003
Posts: 821
Карма: 65
   поощрить/наказать

Location: Россия, Москва

PostPosted: Wed May 24, 2006 8:05 am (спустя 51 минуту; написано за 31 секунду)
   Post subject:
Reply with quote

Дмитрий Котеров
andrewsumin.livejournal.com/ - может быть будет интересно, если ещё не видели (читать снизу вверх, ессна).
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Wed May 24, 2006 7:00 pm (спустя 10 часов 55 минут; написано за 42 секунды)
   Post subject:
Reply with quote

Миша Спларов
Quote:
Началось с того что пробовали на JS натянуть стандартные понятия ООП. Мучались долго но ничего хорошего не получилось.
А, вообще, полезная ссылка...
Back to top
View user's profile Send private message Send e-mail
KES
Участник форума



Joined: 19 Oct 2006
Posts: 214
Карма: 0
   поощрить/наказать

Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина

PostPosted: Sun Feb 25, 2007 12:15 am (спустя 9 месяцев 5 часов 15 минут; написано за 19 минут 31 секунду)
   Post subject:
Reply with quote

совершенно не согласен с этим утверждением
Quote:
Итак, вывод: прототипы объектов доступны по цепочке obj.constructor.prototype.constructor.prototype...
Прошу обратить внимание на на вот эту строку в следующих экспериментах:
Code (JavaScript): скопировать код в буфер обмена
alert( TBasicObj.constructor == TBasicObj.constructor.prototype.constructor ); //true
 
Поэтому НИКАК нельзя добраться к базовому классу через constructor свойтво, потому что его не существует в созданном объекте :D
Почему? А это читайте в моей статье.
Code (JavaScript): скопировать код в буфер обмена
//OBJECT
var TBasicObj= new Object();
alert( TBasicObj.prototype );    //undefined
alert( TBasicObj.constructor )//function Object() { [native code] }

alert( TBasicObj.constructor == TBasicObj.constructor.constructor ); //true

alert( TBasicObj.constructor.prototype ); //function (){}
alert( TBasicObj.constructor == TBasicObj.constructor.prototype.constructor ); //true


//FUNCTION
var TBasicF= new Function();
alert( TBasicF.prototype );    //Empty object
alert( TBasicF.constructor )//function Function() { [native code] }

alert( TBasicF.prototype.prototype ); //undefined
alert( TBasicF.constructor == TBasicF.constructor.constructor ); //true

alert( TBasicF.prototype.constructor ); //function anonymous(){}
alert( TBasicF.prototype == TBasicF.prototype.constructor.prototype ); //true

alert( TBasicF.constructor.prototype ); //function (){}
alert( TBasicF.constructor == TBasicF.constructor.prototype.constructor ); //true
 
ЗЫ. Могу опровергнуть еще много утверждений описанных в набле 40.
Например вот это:
// Создаем "класс" на лету.
var clazz = function() { alert("Динамическая!") }
var obj = new clazz();
alert(obj.constructor == clazz); // выводит true!

true оно то выводит, а вот сравнивается вовсе не то, что написано!!!
Back to top
View user's profile Send private message
Guest






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


PostPosted: Sun Feb 25, 2007 2:24 am (спустя 2 часа 8 минут; написано за 5 минут 21 секунду)
   Post subject:
Reply with quote

Quote:
Конструктором объекта может быть только объект встроенного класса (обычно это Function)
Я бы сказал, что конструктором объекта может быть только Function!!! и иначе НИКАК

alert( Function.constructor ); //function Function
var f= new Function(); //создается, потому что конструктор функция
alert( f.constructor ); //создали из класса function Function
alert( f ); //function anonymous(){} -- функция
var test1= new f(); //создается

alert( Object.constructor ); //function Function
var o= new Object(); //создается, потому что конструктор функция
alert( o.constructor ); //создали из класса function Object
alert( o ); //[object Object] -- объект
var test2= new o(); //болта!! o - Объект, а не функция

Вывод: можно создавать объекты ТОЛЬКО на основе функций
Back to top
Zeroglif
Участник форума



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


PostPosted: Sun Feb 25, 2007 3:08 am (спустя 44 минуты; написано за 10 минут 49 секунд)
   Post subject:
Reply with quote

Anonymous wrote:
Я бы сказал, что конструктором объекта может быть только Function!!! и иначе НИКАК
Конструктором может быть... конструктор (внутренний метод [[Construct]] плюс new expression в наличии плюс соблюдение определённых требований для Object, Array и т.д.). А заодно условным конструктором может быть и человек, используя инициализаторы... :-)
Back to top
View user's profile Send private message
Zeroglif
Участник форума



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


PostPosted: Sun Feb 25, 2007 3:49 am (спустя 40 минут; написано за 32 минуты 58 секунд)
   Post subject:
Reply with quote

KES wrote:
alert(TBasicObj.constructor == TBasicObj.constructor.constructor ); //true
Неправильно, должно быть false, ибо разные конструкторы (цитировал из //OBJECT).
KES wrote:
alert(TBasicObj.constructor.prototype ); //function (){}
Неправильно, должно быть [object Object], ибо этот объект-прототип создан не конструктором Function (цитировал из //OBJECT).
KES wrote:
true оно то выводит, а вот сравнивается вовсе не то, что написано!!!
Почему не то, значением унаследованного объектом obj от своего прототипа свойства constructor является ссылка на "анонимную функцию", значением переменной clazz является ссылка на ту же функцию, отсюда true.
KES wrote:
Поэтому НИКАК нельзя добраться к базовому классу через constructor свойтво, потому что его не существует в созданном объекте
Почему никак, очень даже как, если после создания конструктора не переопределили созданный им прототип, если не "забили" чем-то не тем свойство constructor у прототипа, если не затенили вышеупомянутое свойство путем присвоения одноимённого свойства у самого объекта, то объект запросто доберётся до своего конструктора.

А где статья-то?
Back to top
View user's profile Send private message
KES
Участник форума



Joined: 19 Oct 2006
Posts: 214
Карма: 0
   поощрить/наказать

Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина

PostPosted: Sun Feb 25, 2007 6:22 pm (спустя 14 часов 33 минуты; написано за 30 минут 34 секунды)
   Post subject:
Reply with quote

//OBJECT -- да, тут ошибочка вышла. должно быть false и [object Object], так как Вы и написали
Zeroglif wrote:
Почему не то, значением унаследованного объектом obj от своего прототипа свойства constructor является ссылка на "анонимную функцию", значением переменной clazz является ссылка на ту же функцию, отсюда true.
Code (JavaScript): скопировать код в буфер обмена
var clazz = function() { alert("!") }
var obj = new clazz();
alert(obj.constructor == clazz); //
 
Когда пишете obj.constructor, то создается впечатление, что obj имеет свое собственное свойство constructor, на самом деле оно берется со свойства __proto__. Это свойство мало где упоминатеся и о нем мало кто знает! Поиск свойства у объекта происходит по следующему алгоритму:
1. Проверить свойство локально и вернуть значение, если свойство существует
2. Проверить существование свойства в __proto__ рекурсивно и вернуть значение, если свойство существует
3. Вернуть 'undefined'
Code (JavaScript): скопировать код в буфер обмена
function findProperty( object, property ) {
 if( object[property] !== undefined ) { return object[property];}

 var curr= object;
 while( curr instanceof Object ) {
  if( curr.__proto__[property] !== undefined ) return curr.__proto__[property];
  curr= curr.__proto__;
  }

 return undefined;
 }
Функцию поиска свойства в объекте можно оптимизировать:
Code (JavaScript): скопировать код в буфер обмена
function findProperty( object, property ) {

 var curr= object;
 while( curr instanceof Object ) {
  if( curr[property] !== undefined ) return curr[property];
  curr= curr.__proto__;
  }

 return undefined;
 }
Пример поиска
Code (JavaScript): скопировать код в буфер обмена
var obj1= function(){ alert( '1' ); };
alert( obj1.prototype );
obj1.prototype.a= '1234';

var obj2= function(){ alert( '2' ); };
obj2.prototype= new obj1();

var obj3= function(){ alert( '3' ); };
obj3.prototype= new obj2();

var test= new obj3();


alert( findProperty( test, 'a' )  ); //1234
alert( findProperty( test, 'b' ) ); //undefined
alert( test.a === findProperty( test, 'a' ) ); //true
alert( test.b === findProperty( test, 'b' ) ); //true
 
Последние два вывода true говорят нам о том, что результат работы нашей функции не отличается от стандартных механизмов!


Поэтому пример Дмитрия Котерова я бы модифицировал следующим образом:
Code (JavaScript): скопировать код в буфер обмена
var clazz = function() { alert("!") }
var obj = new clazz();
alert(obj.__proto__.constructor == clazz); //
 
Здесь у читателя должно сформировать правильное видение происходящего. Тут ясно, что:
1) наш obj может не иметь конструктора, поэтому вызывая obj.constructor() мы на самом деле АВТОМАТИЧЕСКИ вызываем конструктор базового класса (объекта): obj.__proto__.constructor()

2) наш obj может иметь свой конструктор, но в этом случае мы обязаны вызвать констуктор базового класса (объекта) вручную: obj.constructor= function(){ this.__proto__.constructor( arguments ) };
Если нужно вызвать конструктор базового класса с другими параметрами:
this.__proto__.constructor( params, you, want, 12345 ) };
Zeroglif wrote:
Почему никак, очень даже как, если после создания конструктора не переопределили созданный им прототип, если не "забили" чем-то не тем свойство constructor у прототипа, если не затенили вышеупомянутое свойство путем присвоения одноимённого свойства у самого объекта, то объект запросто доберётся до своего конструктора.alert(
Не буду далеко ходить, возьмем встроенные типы
Code (JavaScript): скопировать код в буфер обмена
Object.constructor == Object.constructor.prototype.constructor ); //true
Object.constructor == Object.constructor.prototype.constructor.prototype.constructor ); //true
 
Может продолжим?
Code (JavaScript): скопировать код в буфер обмена
alert( Function.constructor == Function.constructor.prototype.constructor ); //true
var o= new Object();
alert( o.constructor == o.constructor.prototype.constructor ); //true
var f= new Function();
alert( f.constructor == f.constructor.prototype.constructor ); //true
var of= new f();
alert( of.constructor == of.constructor.prototype.constructor ); //true
 
Чем же является на самом деле класс (объект) Object?
Object - это обычная "смертная" переменная (переменная === экземпляр ОБЪЕКТа не класса Object!!!) и мы её можем использовать следующим образом
Code (JavaScript): скопировать код в буфер обмена
Object.a= 123;
Object.b= 456;
Object.add= function() {
 return this.a + this.b;
 }
alert( Object.a + Object.b ); //579
alert( Object.add() ); //579
 
Все эти действия никак не отразиться на производных классах(объектах), т.е. на наследовании;
Чтобы наша переменная могла участвовать в наследовании, т.е. быть классом, она должна иметь конуструктор и прототип
1) Конструктор - так как на основе Object будет создан пустой объект, то от конструктора не требуется никаких действий, поэтому он имеет следующую форму:
function(){};
2.а) Прототип - так как Object должен быть самым первым классом в цепи наследования, то он должен иметь пустой прототип
2.б) Прототип - так как Object не является производным ни от какого класса, то он должен иметь пустой проптотип

Пустой прототип:
 1) нет свойств для наследования
 2) нет конструктора
Back to top
View user's profile Send private message
Г.О.
Участник форума



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

Location: Ленинград

PostPosted: Sun Feb 25, 2007 6:35 pm (спустя 12 минут; написано за 53 секунды)
   Post subject:
Reply with quote

KES wrote:
Object - это обычная "смертная" переменная (переменная === экземпляр ОБЪЕКТа не класса Object!!!) и мы её можем использовать следующим образом
Object это функция, используемая в качестве конструктора при создании "простого" объекта.
KES wrote:
Все эти действия никак не отразиться на производных классах(объектах), т.е. на наследовании;
А с какой стати данные действия хоть как-то должны были отразиться на наследовании?
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Sun Feb 25, 2007 7:27 pm (спустя 52 минуты; написано за 2 минуты 40 секунд)
   Post subject:
Reply with quote

KES
Quote:
Чем же является на самом деле класс (объект) Object?
Вообще-то на вопросы подобного рода в ECMAScript Language Specification (Edition 3 Final) есть подробнейшие ответы начиная с главы 4.2.1 Objects и далее...
Back to top
View user's profile Send private message Send e-mail
Zeroglif
Участник форума



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


PostPosted: Sun Feb 25, 2007 7:59 pm (спустя 31 минуту; написано за 44 минуты 17 секунд)
   Post subject:
Reply with quote

KES wrote:
Когда пишете obj.constructor, то создается впечатление, что obj имеет свое собственное свойство constructor, на самом деле оно берется со свойства __proto__. Это свойство мало где упоминатеся и о нем мало кто знает!
Дружище, вы пишете с явным перекосом в сторону некоторых определённых реализаций ECMAScript(ES), __proto__ - это расширение (движки Mozilla, Macromedia...), во множестве реализаций (включая самую распространённую - JScript) прямого доступа к объекту-прототипу нет. Поэтому я бы на вашем месте не выходил бы за рамки терминологии ES, где неявная связь с объектом-прототипом определена как [[Prototype]].
KES wrote:
Поэтому пример Дмитрия Котерова я бы модифицировал следующим образом
Опять, не все так умеют (__proto__), а потом по сути это мало что меняет, ну, может кроме того, что прямое обращение к прототипу исключает ситуацию, когда свойство constructor затенено в объекте.
KES wrote:
Object.constructor == Object.constructor.prototype.constructor ; //true
Object.constructor == Object.constructor.prototype.constructor.prototype.constructor ; //true
A что конкретно вы хотите сказать этим примером, ну закольцевали ссылку на конструктор и что? Следующий пример про то же самое...
KES wrote:
Object - это обычная "смертная" переменная
В строгом смысле (в смысле variablе в ES) - это не переменная, а называть можно конечно всячески: свойство, нативный объект, функция, конструктор и т.д.
KES wrote:
Чтобы наша переменная могла участвовать в наследовании, т.е. быть классом, она должна иметь конуструктор и прототип
Само собой, правда, стоит отметить, что наследовании в javascript сквозит во всём, можно не быть переменной и проч.:
Code (JavaScript): скопировать код в буфер обмена
alert( 'наследование'.length ) // -> наследование уже тут
 
Back to top
View user's profile Send private message
KES
Участник форума



Joined: 19 Oct 2006
Posts: 214
Карма: 0
   поощрить/наказать

Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина

PostPosted: Mon Feb 26, 2007 5:13 am (спустя 9 часов 13 минут; написано за 57 минут 21 секунду)
   Post subject:
Reply with quote

//OBJECT -- да, тут ошибочка вышла. должно быть false и [object Object], так как Вы и написали
Zeroglif wrote:
Почему не то, значением унаследованного объектом obj от своего прототипа свойства constructor является ссылка на "анонимную функцию", значением переменной clazz является ссылка на ту же функцию, отсюда true.
Code (JavaScript): скопировать код в буфер обмена
var clazz = function() { alert("!") }
var obj = new clazz();
alert(obj.constructor == clazz); //
 
Когда пишете obj.constructor, то создается впечатление, что obj имеет свое собственное свойство constructor, на самом деле оно берется со свойства __proto__. Это свойство мало где упоминатеся и о нем мало кто знает! Поиск свойства у объекта происходит по следующему алгоритму:
1. Проверить свойство локально и вернуть значение, если свойство существует
2. Проверить существование свойства в __proto__ рекурсивно и вернуть значение, если свойство существует
3. Вернуть 'undefined'
Code (JavaScript): скопировать код в буфер обмена
function findProperty( object, property ) {
 if( object[property] !== undefined ) { return object[property];}

 var curr= object;
 while( curr instanceof Object ) {
  if( curr.__proto__[property] !== undefined ) return curr.__proto__[property];
  curr= curr.__proto__;
  }

 return undefined;
 }
Функцию поиска свойства в объекте можно оптимизировать:
Code (JavaScript): скопировать код в буфер обмена
function findProperty( object, property ) {

 var curr= object;
 while( curr instanceof Object ) {
  if( curr[property] !== undefined ) return curr[property];
  curr= curr.__proto__;
  }

 return undefined;
 }
Пример поиска
Code (JavaScript): скопировать код в буфер обмена
//ЛИСТИНГ №1
var obj1= function(){ alert( '1' ); };
alert( obj1.prototype );
obj1.prototype.a= '1234';

var obj2= function(){ alert( '2' ); };
obj2.prototype= new obj1();

var obj3= function(){ alert( '3' ); };
obj3.prototype= new obj2();

var test= new obj3();


alert( findProperty( test, 'a' )  ); //1234
alert( findProperty( test, 'b' ) ); //undefined
alert( test.a === findProperty( test, 'a' ) ); //true
alert( test.b === findProperty( test, 'b' ) ); //true
 
Последние два вывода true говорят нам о том, что результат работы нашей функции не отличается от стандартных механизмов!


Поэтому пример Дмитрия Котерова я бы модифицировал следующим образом:
Code (JavaScript): скопировать код в буфер обмена
var clazz = function() { alert("!") }
var obj = new clazz();
alert(obj.__proto__.constructor == clazz); //
 
Здесь у читателя должно сформировать правильное видение происходящего. Тут ясно, что:
1) наш obj НЕ ИМЕЕТ конструктора, поэтому вызывая obj.constructor() мы на самом деле АВТОМАТИЧЕСКИ вызываем конструктор базового класса (объекта): obj.__proto__.constructor()

2) наш obj может иметь свой конструктор, но в этом случае мы обязаны вызвать констуктор базового класса (объекта) вручную:
obj.constructor= function(){ this.__proto__.constructor( arguments ) };
Если нужно вызвать конструктор базового класса с другими параметрами:
this.__proto__.constructor( params, you, want, 12345 ) };
.
.
.
Zeroglif wrote:
Почему никак, очень даже как, если после создания конструктора не переопределили созданный им прототип, если не "забили" чем-то не тем свойство constructor у прототипа, если не затенили вышеупомянутое свойство путем присвоения одноимённого свойства у самого объекта, то объект запросто доберётся до своего конструктора
Не буду далеко ходить за примерами, возьмем встроенные типы
Code (JavaScript): скопировать код в буфер обмена
Object.constructor == Object.constructor.prototype.constructor ); //true
Object.constructor == Object.constructor.prototype.constructor.prototype.constructor ); //true
 
Может продолжим?
Code (JavaScript): скопировать код в буфер обмена
alert( Function.constructor == Function.constructor.prototype.constructor ); //true
var o= new Object();
alert( o.constructor == o.constructor.prototype.constructor ); //true
var f= new Function();
alert( f.constructor == f.constructor.prototype.constructor ); //true
var of= new f();
alert( of.constructor == of.constructor.prototype.constructor ); //true
 
И еще один пример на закуску:
Code (JavaScript): скопировать код в буфер обмена
var obj1= function(){ alert( '1' ); };

var obj2= function(){ alert( '2' ); };
obj2.prototype= new obj1();

var obj3= function(){ alert( '3' ); };
obj3.prototype= new obj2();

var test= new obj3();

alert( test.constructor ); //function(){ alert( '1' ); };
alert( test.constructor == obj1 ); //true
alert( test.constructor.prototype.constructor == obj1 );//true
 
Как видно из примера test.constructor == obj1 и test.constructor.prototype.constructor == obj1. И оно ни как не равно obj3!!!, как следовало ожидать
Немного исправлю Вас:
Zeroglif wrote:
объект запросто НЕ доберётся до своего конструктора
Почему test.constructor != obj3 будет показано ниже
.
.
.
Особенность переменной Object
.
Object - когда-то была (она есть и сейчас) обычной "смертной" переменной и поэтому её можно использовать следующим образом
Code (JavaScript): скопировать код в буфер обмена
Object.a= 123;
Object.b= 456;
Object.add= function() {
 return this.a + this.b;
 }
alert( Object.a + Object.b ); //579
alert( Object.add() ); //579
 
И можно не бояться, что добавление свойства в Object будет влиять на наследование. Потому что всё, что влияет на наследование, это свойство prototype.
По возможностям это свойство ничем не отличается от других и фактически может называться superclass или inherits. Что самое интересное, так это то, что inherits можно сделать массивом, который будет содержать ссылки на базовые классы, и реализовать множественное наследование. Заинтерисовались?


Особенность переменной Object (возможность участвовать в наследовании) является то, что она имеет конструктор, прототип и тип
1) Конструктор - так как Object это пустой объект, то от конструктора не требуется никаких дополнительных действий, поэтому он должен быть пустым:
function(){};
2.а) Прототип - так как Object это самый первый класс в цепи наследования, то он должен иметь пустой прототип
2.б) Прототип - так как Object не является производным ни от какого класса, то он должен иметь пустой прототип

Пустой прототип - это значит то, что у него нет:
 1) свойств для наследования ( т.е. они не определены - undefined )
 2) конструктора ( т.е. указатель на функцию пуст - null )

Если всё выше сказанное выразить программно, то:
Code (JavaScript): скопировать код в буфер обмена
var emptyPrototype= {
 prototype: undefined,
 __proto__: null
 };

var myClass= function a(){
 this.__proto__= function b(){},
 this.prototype= emptyPrototype
 };
Если проверить свойства класса/объекта Object и myClass, то всё сходиться:
Code (JavaScript): скопировать код в буфер обмена
//
alert( Object.prototype ); //[object Object]
alert( Object.__proto__ ); //
  alert( Object.__proto__.constructor == Function )//
  alert( Object.__proto__.prototype.constructor ); //7- //function(){}
  alert( Object.__proto__.prototype.prototype === undefined); //7a
  alert( Object.__proto__.prototype.__proto__ === Object.prototype ); //7b

alert( Object.prototype.constructor == Object )//
alert( Object.prototype.prototype ); //undefined   <---- 7
alert( Object.prototype.__proto__ ); //null   <---- 8
 
.
.
.
Исследование объекта Function:
.
Базовый класс функции есть класс функция
Code (JavaScript): скопировать код в буфер обмена
//
alert( Function.prototype ); //function(){}
alert( Function.__proto__ == Function.prototype ); //true
   alert( Function.__proto__.constructor == Function )//alert( Function.constructor == Function );  //true
   alert( Function.prototype.constructor == Function )//true

alert( Function.prototype.__proto__ != Function.prototype.prototype ); //
alert( Function.prototype.prototype ); //[object Object]
alert( Function.prototype.__proto__ ); //[object Object]

alert( Function.prototype.prototype.__proto__ == Function.prototype.__proto__ ); //true
 
Покопав немного глубже, находим, что 7 и 8 строки получены следующим образом
Code (any language): скопировать код в буфер обмена
Если расписать седьмую строку, то получим:
Code (any language): скопировать код в буфер обмена
7.- Function.prototype.prototype.constructor == function(){}
7.a Function.prototype.prototype.prototype === undefined; //true
7.b Function.prototype.prototype.__proto__ === Object.prototype; //true
Равенство 10 получаем из того, что правые части 8 и 7a равны
Или если переводить с программного на русский язык, то получим что:
1. Прототипом для класса Function является анонимная функция function(){}: alert( Function.prototype ); //function(){}
2. Класс Function является потомком класса Function: alert( Function.__proto__ == Function.prototype ); //true //смотрим алгоритм создания объекта
3. Конструктором для класса Function является функция Function: var Function = function Function(){ [] }; // developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference существуют как глобальные функции, так и глобальные объекты, поэтому существует объект Object и функция Object, существует объект Function и функция Function
4. Конструктором функции function(){} является класс Function:
Function.prototype.constructor == Function, а так как Function.prototype == function(){},то alert( (function(){}).constructor == Function ); //true
Прошу заметить, что alert( Function.prototype == (function(){}) ) выведет false, потому что Function.prototype и (function(){}) это два разных объекта, хотя и имеют одинаковые значения!!!
.
Продолжаем исследование Function
Этот пример показывает, что можно создавать объекты только на основе функций, потому что функция это конструктор для производного класса/объекта
Code (JavaScript): скопировать код в буфер обмена
//Function тест №2
alert( Function.constructor ); //function Function
var f= new Function();         //создается, потому что конструктор функция
alert( f.constructor );        //создали из класса function Function
alert( f );                    //function anonymous(){}  -- функция
var test1= new f();            //создается
//var test2= new test1(); //болта!! test1 - Объект, а не функция

alert( Object.constructor );   //function Function
var o= new Object();           //создается, потому что конструктор функция
alert( o.constructor );        //создали из класса function Object
alert( o );                    //[object Object]  -- объект
//var test2= new o(); //болта!! o - Объект, а не функция
 
Когда в тесте №2 мы создавали новую функцию var f= new Function(); на самом деле мы сделали: f= {}; f.__proto__= Function.prototype(см. алгоритм создание объекта), поэтому наша переменная f получила следующие свойства:
Code (JavaScript): скопировать код в буфер обмена
//
//
var f= new Function();         
alert( f.__proto__ ); //
alert( f.__proto__.constructor == Function );//
alert( f.__proto__.prototype == new function(){} );//
alert( f.__proto__.__proto__ == Object.prototype ); //

alert( f.prototype ); //
alert( f.prototype.constructor ); //
alert( f.prototype.__proto__ == Object.prototype ); //
alert( f.prototype.__proto__.prototype ); //undefined
alert( f.prototype.__proto__.__proto__ ); //null
 
Когда в тесте №2 мы создавали новый объект на основе функции var test1= new f(); на самом деле мы сделали: test1={}; test1.__proto__= f.prototype(см. алгоритм создание объекта), поэтому наша переменная f получила следующие свойства:
Code (JavaScript): скопировать код в буфер обмена
//
//
var f= new Function();
var test1= new f();         
alert( test1.__proto__ ); //
alert( test1.__proto__.constructor == f );//
alert( test1.__proto__.prototype ); //
alert( test1.__proto__.__proto__ == null ); //

alert( test1.prototype ); //
 
.
.
.
Взгляд назад
.
После всех проведенных экспериментов я смог написать функцию эквивалентную стандартному new:
Code (JavaScript): скопировать код в буфер обмена
function newObject( ) {
 var instance= {};

 instance.__proto__= this.prototype;
 this.apply( instance, arguments );

 return instance;
 };


var obj1= function obj1(){ alert( '1' ); };
obj1.prototype.a= '1234';

var obj2= function obj2(){ alert( '2' ); };
obj2.prototype= newObject.apply( obj1 );

var obj3= function obj3(){ alert( '3' ); };
obj3.prototype= newObject.apply( obj2 );

var test= newObject.apply( obj3 );

alert( test.constructor );
alert( test.constructor === obj1 );
Если использовать стандартный new, то вывод программы совпадает с предыдущим примером:
Code (JavaScript): скопировать код в буфер обмена
var obj1= function obj1(){ alert( '1' ); };
obj1.prototype.a= '1234';

var obj2= function obj2(){ alert( '2' ); };
obj2.prototype= new obj1();

var obj3= function obj3(){ alert( '3' ); };
obj3.prototype= new obj2();

var test= new obj3();


alert( test.constructor );
alert( test.constructor === obj1 );
И всетаки, почему test.constructor == obj1, а не obj3. Если внимательно посмотреть на функцию newObject, мы делаем одно неявное действие:
Code (JavaScript): скопировать код в буфер обмена
function newObject( ) {
 var instance= {};

 instance.__proto__= this.prototype;
 [color=red]instance.__proto__.constructor= this.prototype.constructor;[/color]

 this.apply( instance, arguments );
 return instance;
 };
obj1= function obj1(){ alert( '1' ); }; -----> ???
obj2.prototype= new obj1(); ------> obj2.prototype.__proto__= obj1.prototype;
obj3.prototype= new obj2(); ------> obj3.prototype.__proto__= obj2.prototype;
test= new obj3(); ------> test.__proto__= obj3.prototype;
А теперь как в уравнениях на уроках математике сделаем подстановки:
test.__proto__ = obj3.prototype;
test.__proto__.__proto__ = obj3.prototype.__proto__;
test.__proto__.__proto__ = obj2.prototype;
test.__proto__.__proto__.__proto__ = obj2.prototype.__proto__;
test.__proto__.__proto__.__proto__ = obj1.prototype;
test.__proto__.__proto__.__proto__.constructor = obj1.prototype.constructor
test.__proto__.__proto__.__proto__.constructor = function obj1(){ alert( '1' ); }; //Function тест №3 строка 8
test.constructor = obj1
Равенство доказано

Сравнивая Function тест №3 и №4 можно заметить разницу в прототипах созданных объектов f.prototype и test1.prototype
f - это класс, а test1 - это объект
Из этого можно сделать выводы, что нужно различать конструктор объекта и конструктор класса
При создании класса дополнительно инициализируется свойство prototype


В заключение пару примерчиков по которым вы сможете выделить специфические свойства для каждого типа объекта
Code (JavaScript): скопировать код в буфер обмена
//это объект
alert( Object ); //function Object
alert( Object.constructor ); //function Function
alert( Object.prototype ); //[object Object]
alert( Object.prototype.constructor ); //function Object
alert( Object.__proto__ ); //function(){}
alert( Object.__proto__ === Object.__proto__.prototype.constructor ); //true

//это функция
alert( Function ); //function Function
alert( Function.constructor ); //function Function
alert( Function.prototype ); //function(){}
alert( Function.prototype.constructor == Function ); //function Function
alert( Function.__proto__ ); //function(){}
alert( Function.__proto__ === Function.__proto__.prototype.constructor ); //true


//что есть объект, на основе объекта с прототипом объект -- это объект
var o= new Object();
alert( o ); //[object Object]
alert( o.constructor ); //function Object
alert( o.prototype ); //undefined
//alert( o.prototype.constructor ); //???
alert( o.__proto__ ); //[object Object]
//alert( o.__proto__ === o.__proto__.prototype.constructor ); //???

//что есть объект на основе функции у которой прототип функция -- это функция
var f= new Function();
alert( f ); //function anonymous(){}
alert( f.constructor ); //function Function
alert( f.prototype ); //[object Object]
alert( f.prototype.constructor == f ); //function anonymous(){}
alert( f.__proto__ ); //function(){}
alert( f.__proto__ === f.__proto__.prototype.constructor ); //true

//что есть объект на основе функции у которой прототип объект -- это объект
var of= new f();
alert( of ); //[object Object]
alert( of.constructor ); //function anonymous();
alert( of.prototype ); //undefined
//alert( of.prototype.constructor ); //???
alert( of.__proto__ ); //[object Object]
//alert( of.__proto__ === of.__proto__.prototype.constructor );

var fr= function hello(){};
alert( fr ); //function hello(){}
alert( fr.constructor ); //function Function
alert( fr.prototype ); //[object Object]
alert( fr.prototype.constructor == fr ); //function hello(){}
alert( fr.__proto__ ); //function hello(){}
alert( fr.__proto__ === fr.__proto__.prototype.constructor ); //true

var fo= new function hello(){};
alert( fo ); //[object Object]
alert( fo.constructor ); //function hello(){}
alert( fo.prototype ); //undefined
//alert( fo.prototype.constructor == fo ); //???
alert( fo.__proto__ ); //[object Object]
//alert( fo.__proto__ === fo.__proto__.prototype.constructor ); //???
 
Code (JavaScript): скопировать код в буфер обмена
var f= function test(){};
alert( f ); //function test(){};
alert( f.constructor == Function ); //function Function
alert( f.prototype ); //[object Object]
alert( f.__proto__ ); //function test(){};

alert( f.prototype.constructor == f )//true //function test(){}
alert( f.prototype.prototype ); //undefined
alert( f.prototype.__proto__ ); //[object Object]
alert( f.prototype.__proto__.constructor == new f ); //false //function test(){}
alert( f.prototype.__proto__.prototype ); //undefined
alert( f.prototype.__proto__.__proto__ ); //[object Object]
alert( f.prototype.__proto__.__proto__.constructor ); //function Object
alert( f.prototype.__proto__.__proto__.prototype ); //undefined
alert( f.prototype.__proto__.__proto__.__proto__ ); //null
 
Code (JavaScript): скопировать код в буфер обмена
var c1= function a(){
        };
c1.prototype.prop= 'a';

var c2= function b(){
 };
c2.prototype= new c1();
c2.prototype.prop= 'b';

var c3= function c(){

 };
c3.prototype= new c2();
c3.prototype.prop= 'c';

var o1= new c3();
o1.prop= 'd';
alert( c1 );//function a(){}
alert( c2 );//function b(){}
alert( c3 );//function c(){}
alert( o1.prop );//d
alert( o1.__proto__.prop );//c
alert( o1.__proto__.__proto__.prop );//b
alert( o1.__proto__.__proto__.__proto__.prop );//a
 
Code (JavaScript): скопировать код в буфер обмена
function newClass( className, baseClass, props, constr ) {
 constr.prototype.toString= function() { return className; };
 return constr;
 }


//name of new class, base class object, properties of new class, constructor of new class
var TObject= newClass( 'TObject', null, null, function a() {
 var tmp= this.constructor;
 alert( 'TObject: Constructor of ' + this + '\n' + tmp);
});
TObject.prototype.b= 'TObject';

var TDerive= newClass( 'TDerive', TObject, null, function b() {
 var tmp= this.constructor;
 alert( 'TDerive: Constructor of ' + this + '\n' + tmp);
});
TDerive.prototype.b= 'TDerive';
//TDerive.prototype= new TObject; //1

alert( 'Programm start' );
var derive= new TDerive();
//TDerive.prototype= new TObject; //2
alert( 'begin' );
alert( derive.__proto__.prototype );//a1
alert( derive.__proto__.__proto__ );//a2
alert( TDerive.prototype.prototype );//b1
alert( TDerive.prototype.__proto__ );//b2
alert( derive.__proto__ == TDerive.prototype );
alert( derive.a + ' ' + derive.b );//I
TObject.prototype.a= 'asdf';
alert( derive.a + ' ' + derive.b );//II
TDerive.prototype.a= 123;
alert( derive.a + ' ' + derive.b );//III
 
Code (any language): скопировать код в буфер обмена
Code (any language): скопировать код в буфер обмена
var c1= function a(){};
var c2= function b(){}
alert( c2.prototype.constructor ); //function b(){}
c2.prototype= new c1();
alert( c2.prototype.constructor ); //function a(){}


Last edited by KES on Tue Mar 06, 2007 4:20 pm; edited 5 times in total
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Mon Feb 26, 2007 8:38 am (спустя 3 часа 25 минут; написано за 9 минут 44 секунды)
   Post subject:
Reply with quote

KES wrote:
ЕЩЕ будут исправления
Пожалуйста:
Quote:
var f= new Function(); на самом деле мы сделали: f= {};
Ничего подобного Вы не сделали. Нет там {}.
Quote:
2.а) Прототип - так как myClass должен быть самым первым классом в цепи наследования, то он должен иметь пустой прототип
2.б) Прототип - так как myClass не является производным ни от какого класса, то он должен иметь пустой прототип
var myClass= function a(){
 this.__proto__= function b(){},
 this.prototype= emptyPrototype
 };
Что значит "должен иметь пустой прототип"? При создании объекта типа Function итак создается пустой прототип. А вот эта запись this.prototype= emptyPrototype - так это вообще нонсенс. Сумеете сами объяснить, почему это бессмысленно?
Quote:
я смог написать функцию эквивалентную стандартному new
Зачем? Оператор new перестал работать?
Quote:
объект Object и функция Object, существует объект Function и функция Function
Каждая упомянутая пара объект/функция - это один объект, называющийся Native ECMAScript Object. Такие объекты если имеют св-во [[Call]] - то в св-ве [[Class]] будет "Function" (Object, Array, String и т.д), если нет св-ва [[Call]] - в св-ве [[Class]] будет "Object" (Math, к примеру).
Back to top
View user's profile Send private message Send e-mail
Zeroglif
Участник форума



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


PostPosted: Mon Feb 26, 2007 1:13 pm (спустя 4 часа 35 минут; написано за 28 минут 17 секунд)
   Post subject:
Reply with quote

KES wrote:
Как видно из примера test.constructor == obj1 и test.constructor.prototype.constructor == obj1. И оно ни как не равно obj3!!!, как следовало ожидать
Я же специально описал условия:
KES wrote:
если после создания конструктора не переопределили созданный им прототип, если не "забили" чем-то не тем свойство constructor у прототипа, если не затенили вышеупомянутое свойство путем присвоения одноимённого свойства у самого объекта
A вы как раз переопределили прототип, в этом случае обычно (если это необходимо) следующей за переопределением строкой восстанавливают ссылку на "истинный" конструктор.
Back to top
View user's profile Send private message
KES
Участник форума



Joined: 19 Oct 2006
Posts: 214
Карма: 0
   поощрить/наказать

Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина

PostPosted: Mon Feb 26, 2007 3:00 pm (спустя 1 час 46 минут)
   Post subject:
Reply with quote

to AKS:
 Если ссылаетесь на документацию, будьте любезны предоставить линк

to All:
 Если кто не согласен с каким-либо утверждением просьба опровергать кодом
 [quote="Г.О."А с какой стати данные действия хоть как-то должны были отразиться на наследовании?[/quote]
 Ни с какой стати. Там же ясно написано ,что Все эти действия никак не отразиться на производных классах(объектах), т.е. на наследовании; Не надо задавать глупых вопросов. Эта статья имеет исследовательский характер, чтобы знать, что происходит за кулисами, когда создаем объект/класс. Поэтому будут утверждаться очевидные вещи. Если Вы заметили неточности или не согласны, то просьба опровергать кодом с коментами как и что

Object.constructor == Object.constructor.prototype.constructor ); //true
Object.constructor == Object.constructor.prototype.constructor.prototype.constructor ); //true
Zeroglif wrote:
A что конкретно вы хотите сказать этим примером, ну закольцевали ссылку на конструктор и что? Следующий пример про то же самое...
Я не кольцевал, оно закольцовано изначально, а хочу сказать, что вот это утверждение в набле 40 неверно
Quote:
Итак, вывод: прототипы объектов доступны по цепочке obj.constructor.prototype.constructor.prototype..., а не obj.prototype.prototype,
Back to top
View user's profile Send private message
KES
Участник форума



Joined: 19 Oct 2006
Posts: 214
Карма: 0
   поощрить/наказать

Location: сВознесеновка, Мелитопольский р-н, Запорожская обл. Украина

PostPosted: Mon Feb 26, 2007 3:03 pm (спустя 3 минуты; написано за 32 секунды)
   Post subject:
Reply with quote

Zeroglif wrote:
KES писал(а):
если после создания конструктора не переопределили созданный им прототип, если не "забили" чем-то не тем свойство constructor у прототипа, если не затенили вышеупомянутое свойство путем присвоения одноимённого свойства у самого объекта
A вы как раз переопределили прототип, в этом случае обычно (если это необходимо) следующей за переопределением строкой восстанавливают ссылку на "истинный" конструктор.
Возможно я ошибся, не могли бы вы показать эту строку кода?
Back to top
View user's profile Send private message
Г.О.
Участник форума



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

Location: Ленинград

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

Quote:
Ни с какой стати. Там же ясно написано ,что Все эти действия никак не отразиться на производных классах(объектах), т.е. на наследовании; Не надо задавать глупых вопросов.
Вот чего не надо, так это писать чепуху таким миссионерским тоном.
Quote:
Если Вы заметили неточности или не согласны, то просьба опровергать кодом с коментами как и что
Я абсолютно с этим согласен. Я просто не понимаю зачем вы это привели. Разве кто-то утверждал обратное? Я, например, могу написать:
Code (JavaScript): скопировать код в буфер обмена
var x = 10;
alert( x ); //
 
мне дадут какую-нибудь премию за это открытие?
Back to top
View user's profile Send private message
Zeroglif
Участник форума



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


PostPosted: Mon Feb 26, 2007 3:40 pm (спустя 15 минут; написано за 14 минут 57 секунд)
   Post subject:
Reply with quote

KES wrote:
хочу сказать, что вот это утверждение в набле 40 неверно
Меня вдруг осенило - вы не читали эту ветку с начала, в прошлом году вот тут (forum.dklab.ru/viewtopic.php?p=102530#102530), тут (forum.dklab.ru/viewtopic.php?p=102575#102575) и дальше по постам обозначены неточности в набле. К сожалению (а может к счастью) автор оставил наблу без каких-либо последующих изменений/ремарок, не зайдя в форум, читатель или останется с неверным истолкованием, или будет заходить каждый февраль с критикой. ;-)
KES wrote:
Возможно я ошибся, не могли бы вы показать эту строку кода?
Вы не ошиблись, вот ваш код:
Code (JavaScript): скопировать код в буфер обмена
var obj1= function(){ alert( '1' ); };

var obj2= function(){ alert( '2' ); };
obj2.prototype= new obj1();

var obj3= function(){ alert( '3' ); };
obj3.prototype= new obj2();

var test= new obj3();

alert( test.constructor ); //function(){ alert( '1' ); };
alert( test.constructor == obj1 ); //true
alert( test.constructor.prototype.constructor == obj1 );//true
 
В данном случае конструктором объекта test является функция obj3, но перед созданием объекта прототип был вами переопределён. Отсюда свойство constructor прототипа указывает уже совершенно на другой объект. Но это не означает, что в идеальных условиях (о которых я писал выше) свойство constructor не укажет на верный конструктор объекта. Укажет и объект сможет обратиться к своему конструктору.
KES wrote:
Если кто не согласен с каким-либо утверждением просьба опровергать кодом
Вот если бы вы более конкретизировали выводы. Я (без кода, сорри) :-) принципиально не согласен с использованием в качестве обоснования __proto__ , как с расширением (способным на баги и не поддерживаемом много где), не согласен с тем, что полезно в javascript использовать классовую терминологию, не согласен с пустым прототипом. Согласен с вашим исследованием Function и вообще с ролью конструктора в наследовании.
Back to top
View user's profile Send private message
AKS
Участник форума



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


PostPosted: Mon Feb 26, 2007 7:48 pm (спустя 4 часа 8 минут; написано за 3 минуты 12 секунд)
   Post subject:
Reply with quote

KES wrote:
Если ссылаетесь на документацию, будьте любезны предоставить линк
Я бы с удовольствием, но мне не встречалась он-лайн документация. Често говоря, думал, раз уж Вы так увлечены этим "делом", то у Вас, как и меня, есть под рукой pdf (у меня-то в мониторе pdf, а "в зубах" - распечатка). Кстати, вот "на всякий случай" линк на ECMA-262.pdf (www.ecma-international.org/publications/standards/Ecma-262.htm)...
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



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


PostPosted: Tue Feb 27, 2007 1:17 am (спустя 5 часов 29 минут; написано за 1 минуту 36 секунд)
   Post subject:
Reply with quote

Знаете, что я для себя отметил, прочитав (правда, бегло) весь этот топик... А вот что. Когда понадобится собеседовать человека на должность классного JavaScript-программиста, основное требование к нему будет - прекрасно разбираться во всей описанной выше кухне. Не больше и не меньше. Потому что сам я в ней, похоже, разбираюсь недостаточно хорошо.
Back to top
View user's profile Send private message Send e-mail
Zeroglif
Участник форума



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


PostPosted: Tue Feb 27, 2007 1:35 am (спустя 17 минут; написано за 5 минут)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
основное требование к нему будет - прекрасно разбираться во всей описанной выше кухне. Не больше и не меньше. Потому что сам я в ней, похоже, разбираюсь недостаточно хорошо.
Кто ж тогда будет выявлять, насколько прекрасен претендент? ;-) А ветку эту надо бы прикрыть... за то, что шпаргалка она бессовестная (местами, правда, чуток неразборчивая)... ;-)
Back to top
View user's profile Send private message
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 3 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