наследование в 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();
Точнее интересуют следующие вопросы: почему объект в первой строке создается без проблем, хотя его "класс" описывается ниже? почему в созданный объект не попадают методы, которые имеются в прототипе? Если создать объект в коде ниже строк описывающих наследование, то объект будет содержать все методы. Возможно, это простые вопросы, но я не могу самостоятельно найти на них ответы, помогите, пожалуйста, разобраться. |
Прототип !== объект. Если вы сделали прототипом объекта массив, сам он от этого массивом не станет. Поэтому метод push и не работает.
|
Цитата:
|
А при чем тут наследование?
|
Цитата:
|
Ну на самом деле во всех современных движках он станет почти массивом, так как особые Сеттеры, про которые говорили в соседней теме - пронаследуются. Правда в v8 например этот объекта не удастся использовать как массив для передачи параметров в метод apply. Это можно посмотреть в исходных кодах, выглядит примерно так:
function apply(object, array){
if(!Array.isArray(array) || !array instanceof Arguments) throw new TypeError('...');
// ...
}
Естественно там внутренние методы используются, хотя isArray тоже вернёт волс на самом деле. В то время как в SpiderMonkey вернёт тру, если не ошибаюсь. Там полностью наследуется поведение массива. То есть такой новый объект и есть массив. |
Цитата:
И делать объект массивом всё же не нужно, на мой взгляд. Зачем?) |
Первый раз парсер пробегается по коду, запоминая 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);
|
trikadin,
Ну я и написал, что не кроссбраузерно, даже привёл пример с v8. А нужно это было мне, для матриц в WebGL, можно выкрутиться там конечно по другому, на так было бы красивее :) |
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);
|
| Часовой пояс GMT +3, время: 03:01. |