Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Есть ли разумное объяснение столь чрезмерной сложности наследования в js? (https://javascript.ru/forum/misc/37293-est-li-razumnoe-obyasnenie-stol-chrezmernojj-slozhnosti-nasledovaniya-v-js.html)

megaupload 14.04.2013 22:03

Цитата:

Сообщение от Aetae
Взяли и убили у человека зарождающееся понимание...))

вот я млять специально ни слова не говорил ни про чо такое а) а он все засрал мне

father_gorry 15.04.2013 11:14

Почему наследования не происходит? Я проверил, скрипт не создает ошибок.
var Wall = new function(){
	this.color = "red";
}
var Room = new function(){
	this.size = "small";
}
Room.prototype = Wall; //объявляем, что Room наследуктся от Wall
Room.prototype.color="white"; //можно задать через Wall.color - будет то же самое. 
console.log(Room.prototype.color, Wall.color); //Проверили, действительно так.

console.log(Room.color); //Undefined! Опа. Наследования не произошло.

father_gorry 15.04.2013 11:54

А всё, у меня получилось "наследование с помощью цепочек прототипов". Только выглядит это очень грустно.
var Animal = function(){
	this.prototype = new function(){//создаем базовый прототип
		this.walk = true;
	}
}
var Cat = function(){
	this.prototype = new Animal();//наследуем от Animal
}
console.log(new Cat().walk);//не получилось
console.log(new Cat().prototype.prototype.walk); //true /A так - работает

Цепочки вида Object.prototype.prototype.prototype.prototype.pro totype.property - неудобны, потому что если убрать элемент из последовательности наследования, то придется редактировать абсолютно все вызовы.

Aves 15.04.2013 12:02

Цитата:

Сообщение от father_gorry (Сообщение 246246)
Почему наследования не происходит? Я проверил, скрипт не создает ошибок.
var Wall = new function(){
	this.color = "red";
}
var Room = new function(){
	this.size = "small";
}
Room.prototype = Wall; //объявляем, что Room наследуктся от Wall
Room.prototype.color="white"; //можно задать через Wall.color - будет то же самое. 
console.log(Room.prototype.color, Wall.color); //Проверили, действительно так.

console.log(Room.color); //Undefined! Опа. Наследования не произошло.

Потому что код бессмысленный. Если опустить тонкости, то можно сказать, что у объектов нет прототипов, у них есть конструкторы. Прототипы устанавливаются у конструкторов. А вы у объекта Room сами создаете свойство prototype, а ничего не "объявляете". Оно к прототипам и наследованию никакого отношения не имеет, просто назвали вы его так же. То что у вас написано можно записать короче, заменив название prototype на obj например:
var Wall = {color:'red'};
var Room = {size:'small', obj: Wall}; //{size:'small', obj: {color:'red'}}

Hekumok 15.04.2013 12:02

Цитата:

Сообщение от father_gorry (Сообщение 246246)
Почему наследования не происходит? Я проверил, скрипт не создает ошибок.

var Wall = new function(){
	this.color = "red";
} // объявили функцию-конструктор и тут же вызвали её, создался объект со свойством color, присвоили переменной Wall ссылку на этот объект
var Room = new function(){
	this.size = "small";
} // объявили функцию-конструктор и тут же вызвали её, создался объект со свойством size, присвоили переменной Room ссылку на этот объект
Room.prototype = Wall; /* здесь мы нифига НЕ объявляем, что Room наследуктся от Wall!
В этой строчке мы записываем в свойство prototype объекта Room ссылку на объект Wall
Ведь свойство объекта prototype - это не прототип объекта! прототип находится в скрытом свойстве [[Prototype]] объекта (в некот. браузерах прототип доступен через свойство __proto__)
*/
Room.prototype.color="white"; /* можно задать через Wall.color - будет то же самое - да, это правда)) ведь Room.prototype и Wall ссылаются на один и тот же объект
*/
console.log(Room.prototype.color, Wall.color); //Проверили, действительно так.

console.log(Room.color); /* Undefined! Опа. Наследования не произошло.
Ну и спрашивается, какого нафик наследования?
Ессессно, у Room нет свойства color, мы же его не присвоили
*/

Aves 15.04.2013 12:06

Цитата:

Сообщение от father_gorry
А всё, у меня получилось "наследование с помощью цепочек прототипов". Только выглядит это очень грустно.
var Animal = function(){
    this.prototype = new function(){//создаем базовый прототип
        this.walk = true;
    }
}
var Cat = function(){
    this.prototype = new Animal();//наследуем от Animal
}
console.log(new Cat().walk);//не получилось
console.log(new Cat().prototype.prototype.walk); //true /A так - работает

Цепочки вида Object.prototype.prototype.prototype.prototype.pro totype.property - неудобны, потому что если убрать элемент из последовательности наследования, то придется редактировать абсолютно все вызовы.

Здесь вы занимаетесь тем же, чем и большинство приходящих на javascript - пишете собственное наследование, вместо того, чтобы разобраться, как оно в нем устроено. И мне интересно, если в наследовании на классах удалить кокой-нибудь промежуточный класс, то все в порядке будет?

DjDiablo 15.04.2013 12:08

Пример наследование из библиотеки createJs с которой сейас работаю
//обьявляем неймспейс
this.createjs = this.createjs||{};

//наследуем
(function() {
    //конструктор
    var Shape = function(prop) {
          //вызов функции инициализации
          this.initialize(prop);
    }

    //наследуем от родителя
    var p = Shape.prototype = new createjs.DisplayObject();

    //сохраним функцию инициализации родителя, вдруг пригодится
    p.DisplayObject_initialize = p.initialize;

    //инициализация, по сути конструктор из классического ООП
    p.initialize=function(prop){
        this.x=prop.x;
        this.y=prop.y;
    }


    // обьявляем новые методы и свойства
    p.graphics = null;
    p.test = function(){ hello() };

    //приватный метод
    function hello(){
        alert('hello');
    }

    //записываем в неймспейс
    this.createjs.Shape=Shape  
})()


хочу разЪяснить один момент.(для новичков)
Главный недостаток вышеприведённого примера в том что вызывается конструктор DisplayObject при наследовании. Иногда это нужно, а иногда недопустимо.

Эта проблема легко решается.
Если вызов контструктора нужен, тогда оставляете
var p = Shape.prototype = new createjs.DisplayObject();

А если ненужен, то пишите
var p = Shape.prototype = Object.create( createjs.DisplayObject.prototype);


+ если вам вдруг понадобится вызвать конструктор родителя (иногда используется цепочка конструкторов) вы можете его вызвать через DisplayObject_initialize

вот ради этих возможностей и использован трюк с выносом кода конструктора в функцию initialize

P.S. Однако я сам использую по возможности функцию класс и я не вижу смысла боятся подобных функций.

Hekumok 15.04.2013 12:10

Цитата:

Сообщение от father_gorry
А всё, у меня получилось "наследование с помощью цепочек прототипов".

Никакого наследования у вас не получилось!
Цитата:

Сообщение от father_gorry
Только выглядит это очень грустно.

Да, действительно, ваш код и понимание прототипов выглядит грустно ;)

dmitriymar 15.04.2013 12:52

Цитата:

Сообщение от Aves
Если опустить тонкости, то можно сказать, что у объектов нет прототипов, у них есть конструкторы. Прототипы устанавливаются у конструкторов.

.... здорово , а ничего что ссылка на конструктор это свойство прототипа, а не прототип свойство конструктора ?

dmitriymar 15.04.2013 13:09

Цитата:

Сообщение от Aves
И мне интересно, если в наследовании на классах удалить кокой-нибудь промежуточный класс, то все в порядке будет?

Изменить прототип существующего объекта полностью ? Для этого он может и не быть промежуточным в длинной цепочке. достаточно у одного конструктора полностью сменить прототип .
А что мешает протестить самому? -это несколько строк кода всего
function A(){this.num =10};
function D(){this.num =20};
function B(){}
B.prototype = new A;
var c = new B;
alert(c.num)
B.prototype = new D;
alert(c.num)


Часовой пояс GMT +3, время: 03:08.