21.11.2011, 16:45
|
Новичок на форуме
|
|
Регистрация: 12.10.2011
Сообщений: 6
|
|
наследование в javascript
Добрый день!
Подскажите пожалуйста, почему следующий код так работает:
var todayTimeTable = new timeTable();
function timeTable(){
this.showHeader = function(){
document.write("Расписание на сегодня<br />");
}
}
timeTable.prototype = new Array;
timeTable.prototype.showFirst = function(){
document.write(this[0]);
}
// var todayTimeTable = new timeTable(); - если создать объект здесь,то все методы работают
todayTimeTable.showHeader(); //Расписание на сегодня
todayTimeTable.push("Информатика"); // ошибка todayTimeTable.push is not a function
todayTimeTable.showFirst();
Точнее интересуют следующие вопросы:
почему объект в первой строке создается без проблем, хотя его "класс" описывается ниже?
почему в созданный объект не попадают методы, которые имеются в прототипе?
Если создать объект в коде ниже строк описывающих наследование, то объект будет содержать все методы.
Возможно, это простые вопросы, но я не могу самостоятельно найти на них ответы, помогите, пожалуйста, разобраться.
|
|
21.11.2011, 16:52
|
|
Модератор
|
|
Регистрация: 27.04.2010
Сообщений: 3,417
|
|
Прототип !== объект. Если вы сделали прототипом объекта массив, сам он от этого массивом не станет. Поэтому метод push и не работает.
|
|
21.11.2011, 17:23
|
Новичок на форуме
|
|
Регистрация: 12.10.2011
Сообщений: 6
|
|
Сообщение от trikadin
|
Прототип !== объект. Если вы сделали прототипом объекта массив, сам он от этого массивом не станет. Поэтому метод push и не работает.
|
Из этого следует, что объект всегда нужно создавать после указания прототипа?
|
|
21.11.2011, 17:38
|
|
Профессор
|
|
Регистрация: 15.02.2011
Сообщений: 471
|
|
А при чем тут наследование?
|
|
21.11.2011, 17:56
|
|
Модератор
|
|
Регистрация: 27.04.2010
Сообщений: 3,417
|
|
Сообщение от mat5978
|
Из этого следует, что объект всегда нужно создавать после указания прототипа?
|
Из этого следует, что не нужно прототип делать массивом. Массивом объект всё равно не станет)
|
|
21.11.2011, 18:20
|
|
Профессор
|
|
Регистрация: 06.05.2009
Сообщений: 1,163
|
|
Ну на самом деле во всех современных движках он станет почти массивом, так как особые Сеттеры, про которые говорили в соседней теме - пронаследуются. Правда в v8 например этот объекта не удастся использовать как массив для передачи параметров в метод apply. Это можно посмотреть в исходных кодах, выглядит примерно так:
function apply(object, array){
if(!Array.isArray(array) || !array instanceof Arguments) throw new TypeError('...');
// ...
}
Естественно там внутренние методы используются, хотя isArray тоже вернёт волс на самом деле. В то время как в SpiderMonkey вернёт тру, если не ошибаюсь. Там полностью наследуется поведение массива. То есть такой новый объект и есть массив.
__________________
Нужно равняться на лучших, а не оправдываться за счёт худших.
|
|
21.11.2011, 18:54
|
|
Модератор
|
|
Регистрация: 27.04.2010
Сообщений: 3,417
|
|
Сообщение от Nekromancer
|
Ну на самом деле во всех современных движках он станет почти массивом
|
Сильно сомневаюсь, что это кроссбраузерно.
И делать объект массивом всё же не нужно, на мой взгляд. Зачем?)
|
|
21.11.2011, 20:00
|
|
Профессор
|
|
Регистрация: 06.05.2008
Сообщений: 765
|
|
Первый раз парсер пробегается по коду, запоминая function, не заглядывая во внутренности. Т.е. пробежавшись, он знает, что timeTable есть. Поэтому ошибки не возникает и присваивание происходит.
Я у себя попроверял.
Если прототип классу присваивается после создания объекта, объект остается без данных прототипа...
Спецификацию не читал, если кто читал - буду рад услышать комментарий по этому поводу.
function Animal(name) {
this.name = name
this.canWalk = true
}
function Rabbit(name) {
this.name = name
}
big = new Rabbit('Chuk')
Rabbit.prototype = new Animal("скотинка");
small = new Rabbit('Gek')
alert(big.canWalk);
alert(small.canWalk);
Последний раз редактировалось Snipe, 21.11.2011 в 20:02.
|
|
21.11.2011, 21:01
|
|
Профессор
|
|
Регистрация: 06.05.2009
Сообщений: 1,163
|
|
trikadin,
Ну я и написал, что не кроссбраузерно, даже привёл пример с v8.
А нужно это было мне, для матриц в WebGL, можно выкрутиться там конечно по другому, на так было бы красивее
__________________
Нужно равняться на лучших, а не оправдываться за счёт худших.
|
|
21.11.2011, 21:12
|
|
Профессор
|
|
Регистрация: 06.05.2009
Сообщений: 1,163
|
|
Snipe,
Ну видимо, тут дело в том, что для того, что бы расширять уже существующие объекты, нудно расширять прототип, а не заменять его. Заменяя прототип, вы фактически создаёте новый класс. Берём ваш пример и смотрим:
function Animal(name) {
this.name = name
this.canWalk = true
}
function Rabbit(name) {
this.name = name
}
big = new Rabbit('Chuk')
Rabbit.prototype = new Animal("скотинка");
small = new Rabbit('Gek')
alert(big instanceof Rabbit)
alert(small instanceof Rabbit)
По хорошему конечно, наследование нужно организовывать приблезительно так:
var create = Object.create || (Object.create = function(proto){
var constructor = function(){};
constructor.prototype = proto;
return new constructor;
}), inherit = function(childHandler, parent){
var child = function(){
parent.apply(this, arguments);
childHandler.apply(this, arguments);
};
child.prototype = create(parent.prototype);
child.prototype.__parent__ = parent;
return child;
}
var A = function(){
this.foo = 1;
},
B = inherit(function(){
this.bar = 2;
}, A),
c = new B();
alert(c instanceof B);
alert(c instanceof A);
__________________
Нужно равняться на лучших, а не оправдываться за счёт худших.
Последний раз редактировалось Nekromancer, 21.11.2011 в 21:20.
|
|
|
|