«Классы» :]
Всем хорошо известно, что любое упоминание об «классах» в 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"; } });