Lerayne, у тебя 2 ошибки:
1. ты перезаписываешь все свойство prototype новым объектом (стр. 43, 54). В старом содержались всякие Function#apply и Function#call , а в новом их нет. Нужно просто дописывать новые методы в уже существующий объект.
2. функция extend тоже перезаписывает весь prototype, но делает это грамотно - новый объект содержит все нужные методы (наследует их от Function). Таким образом, ты сначала добавляешь новый метод, а затем в extend он затирается вместе со всем prototype. Поэтому нет доступа к func. Нужно сперва вызывать extend, а затем добавлять новые методы.
Поправил твой пример:
function extend(Parent, Child) {
var F = function() { }
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.superclass = Parent.prototype;
}
// функция создания дива с классом и содержимым
function div(className, content){
var elem = document.createElement('DIV');
if (className) elem.className = className;
if (content) elem.innerHTML = content;
return elem;
}
// вариант 2, все свойства и методы добавляются через прототип:
function P(color){
this.populate(color);
}
P.prototype.populate = function(color){
this.container = div('container', 'empty');
this.container.style.background = color;
};
function C(color){
this.populate(color);
this.func();
}
extend(P, C);
C.prototype.func = function(){
this.header = div('header', 'Заголовок!');
this.container.appendChild(this.header);
};
function GC(color){
this.populate(color);
if (this.func) this.func();
this.message = div('messge', 'Сообщение!');
this.container.appendChild(this.message);
}
extend(C, GC);
window.onload = function() {
document.body.appendChild(new P('#FF7777').container); // выводит только "empty"
document.body.appendChild(new C('#FF9999').container); // выводит "empty" и "Заголовок!"
document.body.appendChild(new GC('#FFbbbb').container); // "empty", "Заголовок!" и "Сообщение!"
};
Что бы не делать таких ошибок, можно использовать небольшой конструктор классов. У меня бы получилось так:
var $extend = Object.extend = function(self, obj) {
if (self == null) self = {};
for (var key in obj) self[key] = obj[key];
return self;
}
var Class = {
create: function(parent, declaration) {
function klass() {
this.initialize.apply(this, arguments);
}
if (typeof parent == 'function') {
function F() {}
F.prototype = parent.prototype;
klass.prototype = new F();
} else {
if (parent != null) declaration = parent;
parent = Object;
}
$extend(klass.prototype, declaration).initialize || (klass.prototype.initialize = Function.blank);
klass.$super = parent;
klass.prototype.$super = parent.prototype;
return klass.prototype.constructor = klass;
}
};
function div(className, content) {
var elem = document.createElement('DIV');
if (className) elem.className = className;
if (content) elem.innerHTML = content;
return elem;
}
var P = Class.create({
initialize: function(color) {
this.populate(color);
},
populate: function(color) {
this.container = div('container', 'empty');
this.container.style.background = color;
}
});
var C = Class.create(P, {
populate: function(color) {
P.prototype.populate.call(this, color);
this.header = div('header', 'Заголовок!');
this.container.appendChild(this.header);
}
});
var GC = Class.create(C, {
populate: function(color) {
C.prototype.populate.call(this, color);
this.message = div('messge', 'Сообщение!');
this.container.appendChild(this.message);
}
});
window.onload = function() {
document.body.appendChild(new P('#FF7777').container); // выводит только "empty"
document.body.appendChild(new C('#FF9999').container); // выводит "empty" и "Заголовок!"
document.body.appendChild(new GC('#FFbbbb').container); // "empty", "Заголовок!" и "Сообщение!"
};
Сообщение от Kolyaj
|
Здесь не создаётся экземпляр родительского класса, а просто вызывается его конструктор в контексте текущего this
|
все равно плохо.