Раз за разом я читаю, что удобные библиотеки для создания классов на Javascript, видите ли, не соответствуют идеологии языка и тем, кто их использует просто необходимо учить язык. Такое говорят невежды, которые и сами толком не разобрались ни в самом языке ни в библиотеках, которые они критикуют. И так часто говорят, что я решил написать этот топик и просто давать ссылку
Обёртки в нормальных библиотеках совершенно не противоречат идеологии Javascript и прототипно-ориентированного программирования. Они просто предоставляют удобный интерфейс, алиас для его использования. Конечно, есть библиотеки, которые реализуют «ООП в Javascript» через какие-то черезжопные методы, но сейчас такие во внимание не берем, а рассматриваем их на примере Мутулз.
Например, для конструкции
Введен алиас, который позволяет не повторять
Следующая конструкция для наследования (заметьте, она полностью соотсветствует идеологии Javascript и «ловится» с помощью
Инкапсулируется в такую простую запись:
И еще много-много-много. Суть в том, что оно не нарушает идеологию JavaScript. Оно под неё подстраивается и предоставляет удобный интерфейс, а внутри это всё то же самое, что делали бы профессиональные. Ведь идеология прототипно-ориентированного программирования — это не многословность и постоянные упоминания слова «prototype», а невероятная расширяемость.
А идеологию нарушает как раз другой, очень вредный и очень популярный подход — перегруженный конструктор:
Который нельзя наследовать так, чтобы работал
Я уж молчу про то, что будет в Internet Explorer. Сами проверьте. Можно оставить компьютер включённым на ночь =)
Даже то, что он позволяет реализовать псевдо-приватные методы и переменные не оправдывает этот подход ни на секунду.
Еще раз недостатки перегруженого конструктора, списком:
* не работает
* значительно больший расход памяти
* работает в десятки-сотни раз медленнее
* методы отсутствуют в прототипе
* методы неправильно определяются через hasOwnProperty
Пользуйтесь тем, что вам удобно и приятно пользователям. Если считаете, что MooTools.Class или любая другая подобная библиотека сделает ваше приложение читабельнее и облегчит поддержку — используйте её! И не обращайте внимание на всяких сами знаете кого, которые кричат про идеологию ДжаваСкрипта (а она, несомненно, прекрасна)
UPD: Этот топик был написан как ответ на сообщение aux:
Я не утверждаю, что подход в фреймворках единственно-верный. Просто не следует избегать таких обёрток, как MooTools.Class, если кто-то сказал вам, что она, видите ли, не соответствует идеологии Javascript или что-то подобное. _
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 или любая другая подобная библиотека сделает ваше приложение читабельнее и облегчит поддержку — используйте её! И не обращайте внимание на всяких сами знаете кого, которые кричат про идеологию ДжаваСкрипта (а она, несомненно, прекрасна)
UPD: Этот топик был написан как ответ на сообщение aux:
JS проповедут прототипное ООП, вставлять классовые костыли — не гут. Учите язык и его возможности.
Я не утверждаю, что подход в фреймворках единственно-верный. Просто не следует избегать таких обёрток, как MooTools.Class, если кто-то сказал вам, что она, видите ли, не соответствует идеологии Javascript или что-то подобное. _
