«Классы» :]
Всем хорошо известно, что любое упоминание об «классах» в JavaScript приводит к обильной нецензурной брани и обвинением оппонента, что он не понимает JS и ему не место среди «них».
А зря, ведь в ES6 черным по белому написано class, extends и super.
var Note = Backbone.Model.extend({
initialize: function() { /*...*/ },
author: function() { /*...*/ },
allowedToEdit: function(account) {
return true;
}
});
// Наследуемся от Note
var PrivateNote = Note.extend({
// Переопределяем родительский метод
allowedToEdit: function(account) {
return true;
}
});
App.UserView = Ember.View.extend({
templateName: "user",
firstName: "Albert",
lastName: "Hofmann"
});
var Hello = function (first){ // Конструктор
this.setText(first);
};
// Методы «класса»
Hello.prototype.setText = function (text){
this.text = text;
};
Hello.prototype.say = function (){
alert(this.text);
};
var HelloXXX = function (first, second){
this.setText(first+" "+second);
};
// Наcледуем методы
HelloXXX.prototype = Object.create(Hello.prototype);
// Переопределяем метод
HelloXXX.prototype.setText = function (text){
// Вызываем parent/super
Hello.prototype.setText.call(this, text+"!");
};
// Создаем экземпляр класса
var hello = new HelloXXX("Hi", "Class");
// Вызываем метод "say"
hello.say(); // alert: Hi Class!
Тут вы должны остановить меня и сказать, мы и так всё это знаем, ничего сложно.
И вы правы.
«Классы» и ругань начинаются когда кто-то пытается создать обертку над процессом создания
функции-конструктора, а самое главное вызовов «родительского» метода.
function makeParent(func, parentFunc){
return function (){
var tmp = this.parent/*запомним*/, retVal
this.parent = parentFunc; // текущий родитель
retVal = func.apply(this, arguments);
this.parent = tmp; // востановим
return retVal;
};
}
var Foo = Class.extend({
toString: function (){
return "foo";
}
});
var Bar = Foo.extend({
toString: function (){
return this.parent() + " bar";
}
});
var Foo = ...;
var Bar = Foo.extend({
toString: function (){
return Bar.$superp.toString.call(this) + " bar";
}
});
function base(){
var caller = arguments.callee.caller;
return caller._class._super.prototype[caller._name]
.apply(this, arguments.length
? arguments
: caller.arguments);
}
Вот она, настоящая «магия» :]
def("Foo") ({ /*..*/ });
def("Bar") << Foo ({
toString: function (){
return this._super() + " bar";
}
});
var Foo = ...;
var Bar = Foo.extend({
toString: function __(){
return __.parent.call(this) + " bar";
}
});

