dynamic class A {
function test() {}
}
var a = new A();
var b = new B();
a.test();
b.test();
a.test === b.test // false
a.hasOwnProperty('test'); // true
b.hasOwnProperty('test'); // true
// наследование - как в Java
class B extends A {} // и т.д.
На этом этапе все полностью то же самое, можно сделать в ES3 посредством функции-конструктора:
function A() {
this.test = function () {};
}
// дальше тоже самое
А теперь с хранением свойства «test» в прототипе конструктора:
function A() {}
A.prototype.test = function() {};
var a = new A();
var b = new A();
print a.test === b.test; // true
// наследование
function B() {
this.b = 20;
B.superсlass.call(this, arguments);
}
var __inheritance = function() {};
__inheritance.prototype = A.prototype;
B.prototype = new __inheritance();
B.prototype.constructor = B;
B.superсlass = A; // явная ссылка на «А» для вызова родительских методов
И я предлагаю, когда кто-то захочет сказать «нах классы», говорить: «я вот только знаю статические классы и чуть-чуть слышал о прототипах в JS. Но я хочу заявить — не надо извращаться над JS, примите его таким, какой он есть (да, и… если честно, — это не моя фраза, я ее слышал у одного профи)». Вот тогда будет честно и справедливо! (никого не обижаю — в шутку это все говорю)
> чем же так хорош prototype-подход, какие он дает конкретные преимущества
Основное преимущество — это расшаривание свойств между всеми порожденными объектами. Таким образом, потребляется меньше памяти. Обращение к этим расшаренным свойствам (чаще всего — это методы) происходит посредством делегирования к прототипу конструктора (именно там они хранятся). Главная суть — если свойство не найден в самом объекте, его поиск продолжается в цепи прототипов. Эта цепь и образует наследование.
Я вот когда говорил об эффекте «взрыва» и его «взрывной волне» как раз имел в виду высказывания вроде твоего. Несомненно, это правда, — особенно, касаемо тяжелых оберток или, когда имитируют функции, которые и так в JS есть (например, тема про имитацию функций из PHP). Но это может иметь и побочный эффект — тех же «чучел», — когда могут насмотреться на высказывание профи и потом неосознанно везде писать то же самое (при этом, как я часто замечаю, уровень знаний в JS несколько ниже, чем подается во фразе, услышанной у профи).
> Скоро и железо отстанет. ;)
Э-э, нет ;) Остановятся, если увидят, что «железо» еще не может развиться до определенной стадии (ну, не совсем уж дураки «там сидят»). Касаемо самого JS, — снова абстрактно — любая идеологическая конструкция в нем (хоть замыкания, хоть анонимные функции, хоть динамические объекты, хоть и т.д.) — есть (если очень абстрактно) также синтаксически удобный «сахар» (по отношению к языкам, которые не имеют таких возможностей и вынуждены писать кода в несколько раз больше). При этом, эти удобные обертки в любом случае понесли потери в ресурсах — статические классы быстрее динамических.
Откройте стандарт, пункт 4 (самое начало), второй абзац:
ECMAScript is an object-oriented programming language
> И ООП (статическое), как раз является не оберткой, а эмуляцией.
Да нет здесь никакой эмуляции. Нет здесь никакой статики (и быть не может!). Обычная wrapper-функция-конструктор, которая делает удобным подмену прототипа на нужный.
> классы в более классическом их понимании
Все же, мне кажется, стоит говорить, «статические» классы. Потому что, опять, в Питоне и Руби — тоже классы, они также классические, но при этом — полностью динамические.
> Кому-то это кажется синтаксическими сладостями
Они не должны казаться таковыми. Они являются таковыми в единственно верном понимании (да простят меня все за такую формулировку и не сочтут за навязывание мысли).
> а кто-то именно за это цепляется и видит JS в свете «более ООП»
Так вот расскажите им (каждый раз, когда будете встречать), что это только лишь обертка, и что смотреть нужно (если они хотят понять JS) именно так, и что JS — изначально — ООП-язык и насквозь пронизан наследованием (как пример, можно попросить объяснить, что значит 1.toString();).
> а с точки зрения практического использования, я сильно сомневаюсь. Просто честно, не вижу смысла эмулировать какие-то вещи из других языков просто чтобы синтаксический сахар получить…
Хорошо, еще раз — давайте напишем тройной уровень наследования (и снова, забегая вперед, скажу, что там будет один повторяющийся кусок кода, и мы его вынесем в функцию и назовем ее Inheritance) и посмотрим, как этот код можно оптимизировать с точки зрения reusing'а.
Да и… Рассуждая о понятии класс, я не призываю к оберткам, я как раз отметил, что все это вы можете делать и без оберток. Я лишь хочу, чтобы люди (и те, которые пишут новые обертки, и те, которые не ленятся каждый раз писать «извращенцы») услышали слово «альтернативный» (ООП-подход) и не несли в общество безграмотность, выставляя классовый подход «пуголом» или же не понимая прототипного подхода.
> Все дело в том, что статическая классовая парадигма для многих разработчиков (далеко не всех!) является стандартом при разработке сложных приложений.
Вы это Руби- и Питон- программерам скажите (я имею в виду слово статическая)
да при чем здесь какие-то фреймворки? :) И вообще, что есть фреймворк? У меня, например, был свой фреймворк еще до того, как появились Prototype.js и jQuery. Я просто вынес удобные функции в одно место и юзал их.
Забудьте пока про слово «статика», просто посмотрите сходство (везде одна динамика, разная терминология, слегка отличающаяся идеология, в целом — 80%-сходство):
> Далее, в версии 2.0 вводятся ключевые слова, которые позволят осуществлять ООП, но сейчас этого нет, потому не стоит искать то, чего нет.
Да я и не ищу, я знаю, что оно есть. Я, в принципе, вообще не играю сейчас с Вами в игру «Кто интересней интуитивно догадается, что есть, а что нет в JS», я лишь рассуждаю относительно спецификации ECMAScript (абстрактно раздвигая ее рамки, проводя параллели с другими динамическими ООП-языками — Python и Ruby, где фигурирует понятие class).
По поводу 2.0. Давайте, тоже напишем небольшой пример, и посмотрим, что мы имеем в 2.0. (ES4) и 1.5 (1.6 / 1.7 / 1.8) (ES3). И как мы вынесем один повторяющийся кусок кода в функцию Inheritance.
> Ниже верно сказано «примите его таким, какой он есть».
Да я не сомневаюсь, что верно =) Я принял его таким, какой он есть, и вижу его на «буквах» (на «формулах»), а не на «числах».
Вот и я о том же. А дальше я попрошу взглянуть в сторону Ruby и Python'a — и найти 80%-сходство (при том, что названо это class).
> это два противоречащих друг другу принципа
противоречат только статика-динамика. Руби и Питон — динамические языки (с понятием class, очень схожим с ООП-моделью JS)
> Как эксперимент — зачет, но в проектах такое применять не следует…
да что жы Вы все эту шарманку крутите? ;) Хорошо. Давайте продемонстрируем тройной уровень наследования (я, заранее забегая, скажу — что там будет повторяющийся кусок кода, мы его вынесем (следуя code reuse) в функцию и назовем ее Inheritance).
> язык следует использовать так, как он создан, не надо языку с динамической типизацией и прототипами притягивать за уши парадигмы и приемы других языков.
Вероятно (наиболее), что если человек говорит так, то он сам может не понимать, как работает OOP-модель в JS. Я не знаю, насколько это относится к Вам, буду верить, что в меньшей мере. Внутри обертки — используется именно это. Это лишь синтаксический сахар (не больше, ни меньше! вот — не больше! ни меньше!) для удобного описания наследования.
Скажите, как бы изменилось Ваше отношение к этому сахару, если бы главная оберточная функция была названа не Class, а, например, Inheritance? Или moyaUdobnayaObertkaDlyaPrototypnogoNasledovaniya?
Другой вопрос, что новичкам надо объяснять и показывать на примерах, что есть альтернативная ООП-модель и именно она используется в JS. И обязательно отметить, что смотреть на это все нужно только как на обертку — без изменения прототипной парадигмы.
> Зачем из прототипного языка делать непонятно что…
Да тренируются люди, расслабьтесь Вы :) пишут просто удобные обертки — нет в этом ничего плохого, если они понимают суть вещей. Другой вопрос к Вам — что такое «непонятно что»?
> Инструмент должен работать так, как задумано.
Да он и работает так, как задумано (по-другому просто нельзя в данном случае реализовать)
> К тому же мне кажется, что всякие такие обертки не будут ускорять работу скриптов ;).
Производительность снижается за счет применения синтаксического сахара (часто — удобного).
> Имитируется только синтаксис определения классов как в статической парадигме.
да не только как в статической, Руби с Питоном — динамические
Одна из основных идей статической модели — увеличение производительности за счет того, что не нужно каждый раз анализировать объект при обращении к его пропертям. Вместе с тем, статическая модель менее гибкая в организации. Поэтому, повторю — обе модели имеют свои плюсы и минусы. Не стоит смотреть на эти обертки, как на механизм, позволяющий «довести до ума» :) ООП-модель в JS. Смотрите на эту обертку — просто как на обертку. И всем передайте, что смотреть нужно именно так, тогда понимание различных парадигм (на «буквах», на «формулах», а не на «конкретных числах») придет очень быстро.
Ну тоже одну и ту же пластику не надо заводить постоянно. Ведь любая подобная тема содержит подобный Вашему комментарий. Причем, я склонен полагать, он появляется эфектом «взрывной волны», где «взрывом» являлось высказывание профи (при этом профи видет, как устроен JS и как устроенны другие языки, например Python и Ruby).
Поэтому, мне кажется, лучше подсказывать, помогать новичками понять суть и принципы (проводя параллели и аналогии), а не тыкать их, называя извращенцами.
А теперь вопрос лично к Вам — что Вы подразумеваете под «извращением» в данном случае?
Ну и опять повторю — схожая идеологически модель, используется в Python и Ruby (только там это названо class) — вы не найдете и там статики, которую хотите сымитировать — объекты, классы (которые тоже объекты), их проперти, методы и т.д. — можно менять динамически в рантайме — так же как и в JS. Но — это уже названо class (сходство, естественно, не полное — процентов 80, но идеологически — в одну сторону смотрят). С таким подходом — можно идти в Python и Ruby и менять их организацию — вот только что-то останавливает — там, вроде как, уже есть слово class, да? :)
Код из ES4:
dynamic class A { function test() {} } var a = new A(); var b = new B(); a.test(); b.test(); a.test === b.test // false a.hasOwnProperty('test'); // true b.hasOwnProperty('test'); // true // наследование - как в Java class B extends A {} // и т.д.На этом этапе все полностью то же самое, можно сделать в ES3 посредством функции-конструктора:
function A() { this.test = function () {}; } // дальше тоже самоеА теперь с хранением свойства «test» в прототипе конструктора:
function A() {}
A.prototype.test = function() {};
var a = new A();
var b = new A();
print a.test === b.test; // true
// наследование
function B() {
this.b = 20;
B.superсlass.call(this, arguments);
}
var __inheritance = function() {};
__inheritance.prototype = A.prototype;
B.prototype = new __inheritance();
B.prototype.constructor = B;
B.superсlass = A; // явная ссылка на «А» для вызова родительских методов
а, кстати, — в этом топике холивора не было ))
И я предлагаю, когда кто-то захочет сказать «нах классы», говорить: «я вот только знаю статические классы и чуть-чуть слышал о прототипах в JS. Но я хочу заявить — не надо извращаться над JS, примите его таким, какой он есть (да, и… если честно, — это не моя фраза, я ее слышал у одного профи)». Вот тогда будет честно и справедливо! (никого не обижаю — в шутку это все говорю)
> чем же так хорош prototype-подход, какие он дает конкретные преимущества
Основное преимущество — это расшаривание свойств между всеми порожденными объектами. Таким образом, потребляется меньше памяти. Обращение к этим расшаренным свойствам (чаще всего — это методы) происходит посредством делегирования к прототипу конструктора (именно там они хранятся). Главная суть — если свойство не найден в самом объекте, его поиск продолжается в цепи прототипов. Эта цепь и образует наследование.
Я вот когда говорил об эффекте «взрыва» и его «взрывной волне» как раз имел в виду высказывания вроде твоего. Несомненно, это правда, — особенно, касаемо тяжелых оберток или, когда имитируют функции, которые и так в JS есть (например, тема про имитацию функций из PHP). Но это может иметь и побочный эффект — тех же «чучел», — когда могут насмотреться на высказывание профи и потом неосознанно везде писать то же самое (при этом, как я часто замечаю, уровень знаний в JS несколько ниже, чем подается во фразе, услышанной у профи).
> Скоро и железо отстанет. ;)
Э-э, нет ;) Остановятся, если увидят, что «железо» еще не может развиться до определенной стадии (ну, не совсем уж дураки «там сидят»). Касаемо самого JS, — снова абстрактно — любая идеологическая конструкция в нем (хоть замыкания, хоть анонимные функции, хоть динамические объекты, хоть и т.д.) — есть (если очень абстрактно) также синтаксически удобный «сахар» (по отношению к языкам, которые не имеют таких возможностей и вынуждены писать кода в несколько раз больше). При этом, эти удобные обертки в любом случае понесли потери в ресурсах — статические классы быстрее динамических.
Откройте стандарт, пункт 4 (самое начало), второй абзац:
> И ООП (статическое), как раз является не оберткой, а эмуляцией.
Да нет здесь никакой эмуляции. Нет здесь никакой статики (и быть не может!). Обычная wrapper-функция-конструктор, которая делает удобным подмену прототипа на нужный.
> классы в более классическом их понимании
Все же, мне кажется, стоит говорить, «статические» классы. Потому что, опять, в Питоне и Руби — тоже классы, они также классические, но при этом — полностью динамические.
> Кому-то это кажется синтаксическими сладостями
Они не должны казаться таковыми. Они являются таковыми в единственно верном понимании (да простят меня все за такую формулировку и не сочтут за навязывание мысли).
> а кто-то именно за это цепляется и видит JS в свете «более ООП»
Так вот расскажите им (каждый раз, когда будете встречать), что это только лишь обертка, и что смотреть нужно (если они хотят понять JS) именно так, и что JS — изначально — ООП-язык и насквозь пронизан наследованием (как пример, можно попросить объяснить, что значит 1.toString();).
дело привычки
«не больше! ни меньше!» => ни… ни, конечно (тороплюсь просто)
Хорошо, еще раз — давайте напишем тройной уровень наследования (и снова, забегая вперед, скажу, что там будет один повторяющийся кусок кода, и мы его вынесем в функцию и назовем ее Inheritance) и посмотрим, как этот код можно оптимизировать с точки зрения reusing'а.
ну, тогда и динамическую классовую модель в Руби и Питоном сразу поймете ;)
Вы это Руби- и Питон- программерам скажите (я имею в виду слово статическая)
да при чем здесь какие-то фреймворки? :) И вообще, что есть фреймворк? У меня, например, был свой фреймворк еще до того, как появились Prototype.js и jQuery. Я просто вынес удобные функции в одно место и юзал их.
Забудьте пока про слово «статика», просто посмотрите сходство (везде одна динамика, разная терминология, слегка отличающаяся идеология, в целом — 80%-сходство):
habrahabr.ru/blogs/javascript/40909/#comment_996830
habrahabr.ru/blogs/javascript/40909/#comment_997247
Является. Конечно, является. Это ООП-язык с алтернативной (не дождетесь — я не устану повторять это слово и выделять его курсивом ;)) парадигмой.
ru.wikipedia.org/wiki/Прототипное_программирование
> Далее, в версии 2.0 вводятся ключевые слова, которые позволят осуществлять ООП, но сейчас этого нет, потому не стоит искать то, чего нет.
Да я и не ищу, я знаю, что оно есть. Я, в принципе, вообще не играю сейчас с Вами в игру «Кто интересней интуитивно догадается, что есть, а что нет в JS», я лишь рассуждаю относительно спецификации ECMAScript (абстрактно раздвигая ее рамки, проводя параллели с другими динамическими ООП-языками — Python и Ruby, где фигурирует понятие class).
По поводу 2.0. Давайте, тоже напишем небольшой пример, и посмотрим, что мы имеем в 2.0. (ES4) и 1.5 (1.6 / 1.7 / 1.8) (ES3). И как мы вынесем один повторяющийся кусок кода в функцию Inheritance.
> Ниже верно сказано «примите его таким, какой он есть».
Да я не сомневаюсь, что верно =) Я принял его таким, какой он есть, и вижу его на «буквах» (на «формулах»), а не на «числах».
Вот и я о том же. А дальше я попрошу взглянуть в сторону Ruby и Python'a — и найти 80%-сходство (при том, что названо это class).
> это два противоречащих друг другу принципа
противоречат только статика-динамика. Руби и Питон — динамические языки (с понятием class, очень схожим с ООП-моделью JS)
> Как эксперимент — зачет, но в проектах такое применять не следует…
да что жы Вы все эту шарманку крутите? ;) Хорошо. Давайте продемонстрируем тройной уровень наследования (я, заранее забегая, скажу — что там будет повторяющийся кусок кода, мы его вынесем (следуя code reuse) в функцию и назовем ее Inheritance).
Вероятно (наиболее), что если человек говорит так, то он сам может не понимать, как работает OOP-модель в JS. Я не знаю, насколько это относится к Вам, буду верить, что в меньшей мере. Внутри обертки — используется именно это. Это лишь синтаксический сахар (не больше, ни меньше! вот — не больше! ни меньше!) для удобного описания наследования.
Скажите, как бы изменилось Ваше отношение к этому сахару, если бы главная оберточная функция была названа не Class, а, например, Inheritance? Или moyaUdobnayaObertkaDlyaPrototypnogoNasledovaniya?
Другой вопрос, что новичкам надо объяснять и показывать на примерах, что есть альтернативная ООП-модель и именно она используется в JS. И обязательно отметить, что смотреть на это все нужно только как на обертку — без изменения прототипной парадигмы.
Да тренируются люди, расслабьтесь Вы :) пишут просто удобные обертки — нет в этом ничего плохого, если они понимают суть вещей. Другой вопрос к Вам — что такое «непонятно что»?
> Инструмент должен работать так, как задумано.
Да он и работает так, как задумано (по-другому просто нельзя в данном случае реализовать)
> К тому же мне кажется, что всякие такие обертки не будут ускорять работу скриптов ;).
Производительность снижается за счет применения синтаксического сахара (часто — удобного).
да не только как в статической, Руби с Питоном — динамические
Одна из основных идей статической модели — увеличение производительности за счет того, что не нужно каждый раз анализировать объект при обращении к его пропертям. Вместе с тем, статическая модель менее гибкая в организации. Поэтому, повторю — обе модели имеют свои плюсы и минусы. Не стоит смотреть на эти обертки, как на механизм, позволяющий «довести до ума» :) ООП-модель в JS. Смотрите на эту обертку — просто как на обертку. И всем передайте, что смотреть нужно именно так, тогда понимание различных парадигм (на «буквах», на «формулах», а не на «конкретных числах») придет очень быстро.
эфектом -> *эффектом
Поэтому, мне кажется, лучше подсказывать, помогать новичками понять суть и принципы (проводя параллели и аналогии), а не тыкать их, называя извращенцами.
А теперь вопрос лично к Вам — что Вы подразумеваете под «извращением» в данном случае?