var Foo = new Class({
Extends: Bar,
initialize: function(firstname, lastname) {
this.parent(firstname);
this.lastname = lastname;
},
sayHello: function(){
alert(this.lastname || this.firstname);
}
});
Обёртки в нормальных библиотеках совершенно не противоречат идеологии Javascript и прототипно-ориентированного программирования. Они просто предоставляют удобный интерфейс, алиас для его использования. Конечно, есть библиотеки, которые реализуют «ООП в Javascript» через какие-то черезжопные методы, но сейчас такие во внимание не берем, а рассматриваем их на примере Мутулз.
Например, для конструкции
MyClass = function() {/* constructor */};
MyClass.prototype.firstMethod = function() {/**/};
MyClass.prototype.secondMethod = function() {/**/};
MyClass.prototype.thirdMethod = function() {/**/};
Введен алиас, который позволяет не повторять
MyObject.prototype
. Не обойтись без этой конструкции, а просто не повторять её. Внутри библиотеки будет всё тот же MyClass = new Class({
initialize : function() {/* constructor */},
firstMethod : function() {/**/};
secondMethod: function() {/**/};
thirdMethod : function() {/**/};
});
Следующая конструкция для наследования (заметьте, она полностью соотсветствует идеологии Javascript и «ловится» с помощью
instanceof
)MyAnotherClass = function() {/* constructor */};
var Tmp = function() { }
Tmp.prototype = MyClass.prototype
MyAnotherClass.prototype = new Tmp()
MyAnotherClass.prototype.constructor = MyAnotherClass;
Инкапсулируется в такую простую запись:
MyAnotherClass = new Class({
Extends: MyClass
});
И еще много-много-много. Суть в том, что оно не нарушает идеологию JavaScript. Оно под неё подстраивается и предоставляет удобный интерфейс, а внутри это всё то же самое, что делали бы профессиональные. Ведь идеология прототипно-ориентированного программирования — это не многословность и постоянные упоминания слова «prototype», а невероятная расширяемость.
Перегруженый конструктор
А идеологию нарушает как раз другой, очень вредный и очень популярный подход — перегруженный конструктор:
var MyClass = function() {
/* Начало конструктора */
this.firstMethod = function() {/**/};
this.secondMethod = function() {/**/};
this.thirdMethod = function() {/**/};
/* Конец конструктора, вот такой у нас зашибезный конструктор */
};
var MyAnotherClass = function() {
// Наследование
MyClass.apply(this, arguments);
this.elseOneMethod = function() {/**/};
};
var myAC = new MyAnotherClass();
console.log(myAC instanceof MyClass); // false
Который нельзя наследовать так, чтобы работал
instanceof
, в которой функции создаются каждый раз при создании объекта, из-за чего память течет рекой и рыдает процессор. Вместо того, чтобы создать функцию в одном месте и дать на неё ссылку — будем создавать её каждый раз. Этих функций нету в прототипе (а во встроенных объектах, таких как Array, Number и остальных всё находится именно в прототипе), их нельзя переопределить или получить вне контекста, они неправильно определяются с помощью hasOwnProperty
и работают непозволительно медленно (в сотни раз):var MyClass = function() {
this.method1 = function(){};
};
MyClass.prototype.method2 = function(){};
var myClass = new MyClass;
console.log(myClass.hasOwnProperty('method1')); // true
console.log(myClass.hasOwnProperty('method2')); // false
var Foo = function() {
this.method1 = function(){};
this.method2 = function(){};
this.method3 = function(){};
this.method4 = function(){};
this.method5 = function(){};
this.method6 = function(){};
this.method7 = function(){};
this.method8 = function(){};
this.method9 = function(){};
}
var Bar = function() {};
Bar.prototype.method1 = function(){};
Bar.prototype.method2 = function(){};
Bar.prototype.method3 = function(){};
Bar.prototype.method4 = function(){};
Bar.prototype.method5 = function(){};
Bar.prototype.method6 = function(){};
Bar.prototype.method7 = function(){};
Bar.prototype.method8 = function(){};
Bar.prototype.method9 = function(){};
/**
* Chrome 8
* Foo: 260
* Bar: 26
* Firefox 3.5
* Foo: 22081
* Bar: 158
*/
console.time('Foo');
for (var i = 1000000; i--;) new Foo();
console.timeEnd('Foo');
console.time('Bar');
for (var i = 1000000; i--;) new Bar();
console.timeEnd('Bar');
Я уж молчу про то, что будет в Internet Explorer. Сами проверьте. Можно оставить компьютер включённым на ночь =)
Даже то, что он позволяет реализовать псевдо-приватные методы и переменные не оправдывает этот подход ни на секунду.
Еще раз недостатки перегруженого конструктора, списком:
* не работает
instanceof
в детях* течет память
* работает в десятки-сотни раз медленнее
* методы отсутствуют в прототипе
* методы неправильно определяются через hasOwnProperty
Вывод
Пользуйтесь тем, что вам удобно и приятно пользователям. Если считаете, что MooTools.Class или любая другая подобная библиотека сделает ваше приложение читабельнее и облегчит поддержку — используйте её! И не обращайте внимание на всяких сами знаете кого, которые кричат про идеологию ДжаваСкрипта (а она, несомненно, прекрасна)
Источник: Хабрахабр - JavaScript
Оригинальная страница: Обёртки для создания классов: зло или добро?
Комментариев нет:
Отправить комментарий