Как я уже успел узнать, классы в js можно эмулировать кучей различных способов, один извращённее другого.
1.
function MyClass() {
this.field1 = 666;
this.method1 = MyClass_method1();
this.method2 = MyClass_method2();
// ...
}
function MyClass_method1(x) {
alert("MyClass_method1");
}
function MyClass_method2(x) {
alert("MyClass_method2");
}
Каждый раз перенабирать имя класса в имени "метода" наводит грусть. "Методы" болтаются отдельно. И почему используется NewClass_method1() вместо NewClass_method1 в конструкторе? В конце концов в javascript функции FCO или не FCO?
Самый чистый и опрятный вариант, но и тут оказываются грабли. Оказывается, мегадвижки не в состоянии соптимизировать код и прям-таки вынуждены плодить по новой функции на каждый экземпляр. Ужос, просто.
В связи с этим у меня 4 вопроса:
1. Функции в javascript первоклассные или нет?
1. Какой способ определения класса выбирают РСДН-гуру?
2. Почему оптимизация в пункте 4 невозможна? Что мешает?
3. Насколько скорость вызова метода определённого как MyClass.prototype.method1 отличается от метода, определённого как this.method2
LCR>В связи с этим у меня 4 вопроса: LCR>1. Функции в javascript первоклассные или нет?
Да. В этом отношении Javascript — полноценный функциональный язык.
LCR>1. Какой способ определения класса выбирают РСДН-гуру?
Я не гуру , но использую 4-й способ Большниство всяких фреймворков, насколько знаю, используют его же
LCR>2. Почему оптимизация в пункте 4 невозможна? Что мешает? LCR>3. Насколько скорость вызова метода определённого как MyClass.prototype.method1 отличается от метода, определённого как this.method2
Mamut,
LCR>>В связи с этим у меня 4 вопроса: LCR>>1. Функции в javascript первоклассные или нет?
M>Да. В этом отношении Javascript — полноценный функциональный язык.
А вот почему тогда пишется
По мне например, MyClass_method1() выглядит как вызов без аргументов.
LCR>>1. Какой способ определения класса выбирают РСДН-гуру?
M>Я не гуру , но использую 4-й способ Большниство всяких фреймворков, насколько знаю, используют его же
То есть можно не париться с чрезмерным расходом памяти. Спасибо, это хорошая новость
LCR>>2. Почему оптимизация в пункте 4 невозможна? Что мешает? LCR>>3. Насколько скорость вызова метода определённого как MyClass.prototype.method1 отличается от метода, определённого как this.method2
M>На эти два вопроса, увы, ответов не имею
LCR>>>В связи с этим у меня 4 вопроса: LCR>>>1. Функции в javascript первоклассные или нет?
M>>Да. В этом отношении Javascript — полноценный функциональный язык. LCR>А вот почему тогда пишется LCR>
LCR>По мне например, MyClass_method1() выглядит как вызов без аргументов.
Это, кстати, неправильно. Должен быть именно второй вариант, потому что со скобками — это таки вызов
LCR>>>1. Какой способ определения класса выбирают РСДН-гуру?
M>>Я не гуру , но использую 4-й способ Большниство всяких фреймворков, насколько знаю, используют его же
LCR>То есть можно не париться с чрезмерным расходом памяти. Спасибо, это хорошая новость
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Как я уже успел узнать, классы в js можно эмулировать кучей различных способов, один извращённее другого. LCR>1. LCR>[...] LCR>И почему используется NewClass_method1() вместо NewClass_method1 в конструкторе?
Это ошибка.
LCR>2. LCR>[...] LCR>Уже лучше, но раздражает слово prototype. И имя класса каждый раз нужно снова повторять. И методы опять как-то нехорошо отделены от класса.
Этот способ считается классическим и самым правильным, но не позволяет создавать приватные члены.
LCR>3. LCR>[...]
Впервые вижу.
LCR>4. LCR>[...] LCR>Самый чистый и опрятный вариант, но и тут оказываются грабли. Оказывается, мегадвижки не в состоянии соптимизировать код и прям-таки вынуждены плодить по новой функции на каждый экземпляр. Ужос, просто.
Зато тут можно за счёт замыканий создавать приватные члены.
LCR>В связи с этим у меня 4 вопроса: LCR>1. Функции в javascript первоклассные или нет?
Да.
LCR>1. Какой способ определения класса выбирают РСДН-гуру?
4.
LCR>3. Насколько скорость вызова метода определённого как MyClass.prototype.method1 отличается от метода, определённого как this.method2
Mamut,
LCR>>По мне например, MyClass_method1() выглядит как вызов без аргументов. M>Это, кстати, неправильно. Должен быть именно второй вариант, потому что со скобками — это таки вызов
Ага, разобрался.
LCR>>То есть можно не париться с чрезмерным расходом памяти. Спасибо, это хорошая новость M>Ну, народ не парится, хотя должен был бы, имхо
LCR> this.method1 = function(x) { LCR> alert("MyClass_method1"); LCR> }
LCR> this.method2 = function(x) { LCR> alert("MyClass_method2"); LCR> } LCR>} LCR>[/code] LCR>Самый чистый и опрятный вариант, но и тут оказываются грабли. Оказывается, мегадвижки не в состоянии соптимизировать код и прям-таки вынуждены плодить по новой функции на каждый экземпляр. Ужос, просто.
Я делаю так:
function MyClass()
{
this.Define("method1", function(x)
{
alert("MyClass_method1");
})
}
А Define у меня пихает функцию в прототип объекта. Определен примерно так:
Хотя мне способ номер 2 тоже кажется нормальным. Меня слово prototype не раздражает. В моем способе каждый раз все равно плодится по новому экземпляру функции, но они сразу уничтожаются сборщиком мусора, и у всех объектов получается всего один экземпляр каждого метода, запихнутый в прототип.
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>1. Функции в javascript первоклассные или нет?
--
LCR>1. Какой способ определения класса выбирают РСДН-гуру?
способ 2.
что вам мешает взять правило: один класс=один js файл?
насчет prototype я бы не сказал, что это неудобно. наоборот — визуально сразу все понятно.
тем более можно без prototype объявить в том же модуле еще и вспомогательные функции, не требующие создания экземпляра класса, но так или иначе по смыслу к данному классу относящиеся:
где соответственно set_element — это метод предка MyParentClass.
LCR>2. Почему оптимизация в пункте 4 невозможна? Что мешает?
мешает то, что при создании большого количества объектов данного класса будут тормоза из-за создания множества анонимных функций для каждого метода.
дальше работать они будут практически с той же скоростью, как и созданные любым другим способом.
опять же проблемы с наследованием. частично они решаются через ж:
function MyParentClass(el) {
this.set_element=function(el) {...};
}
function MyChildClass(el) {
this.set_element(el);
}
MyChildClass.prototype=new MyParentClass;
MyChildClass.prototype.method1 = function(x) {
alert("MyChildClass method1");
}
но это действительно решение через ж. да еще плюс создается лишний объект для "сдирания" с него прототипа(шаблона класса).
LCR>3. Насколько скорость вызова метода определённого как MyClass.prototype.method1 отличается от метода, определённого как this.method2
скорость вызова — нинасколько. если и отличается, то на ничтожно малое время.
а вот скорость создания отличаться будет серьезно в случае this.method1=function(){...}.
этот метод неверный, не нужны скобки.
LCR>4. LCR>Самый чистый и опрятный вариант, но и тут оказываются грабли. Оказывается, мегадвижки не в состоянии соптимизировать код и прям-таки вынуждены плодить по новой функции на каждый экземпляр. Ужос, просто.
он не имеет права ничего оптимизировать потому что это — замыкания (closures), которые создаются каждый раз заново.
LCR>В связи с этим у меня 4 вопроса:
<useful comment skipped>
LCR>>2. Почему оптимизация в пункте 4 невозможна? Что мешает? DSD>мешает то, что при создании большого количества объектов данного класса будут тормоза из-за создания множества анонимных функций для каждого метода.
Я имел ввиду что мешает не создавать множество одинаковых анонимных функций для каждого метода.
LCR>>3. Насколько скорость вызова метода определённого как MyClass.prototype.method1 отличается от метода, определённого как this.method2 DSD>скорость вызова — нинасколько. если и отличается, то на ничтожно малое время. DSD>а вот скорость создания отличаться будет серьезно в случае this.method1=function(){...}.
_pk_sly,
LCR>>4. LCR>>Самый чистый и опрятный вариант, но и тут оказываются грабли. Оказывается, мегадвижки не в состоянии соптимизировать код и прям-таки вынуждены плодить по новой функции на каждый экземпляр. Ужос, просто.
__>он не имеет права ничего оптимизировать потому что это — замыкания (closures), которые создаются каждый раз заново.
гхм. Ну что мешает замыкания создавать каждый раз не заново?
LCR>>В связи с этим у меня 4 вопроса:
__>не забываем про способ JSON:
__>file.js __>
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
__>>он не имеет права ничего оптимизировать потому что это — замыкания (closures), которые создаются каждый раз заново. LCR>гхм. Ну что мешает замыкания создавать каждый раз не заново?
Контекст мог измениться. Если не пересоздать замыкание, оно будет со старым контекстом.
LCR>Э... а где тут класс?
П>И получаем ту же проблему, что в варианте 4. Ничем не лучше, чем, собственно, вариант 4.
Даже хуже, чем вариант 4, потому что полученные объекты не будут иметь отдельного, характерного только для них, общего прототипа — их прототип будет прототипом Object. Вопрос-то был не в том, как бы похитрее создать единичный объект, а как создать класс и потом наплодить однотипных объектов, не плодя идентичных функций.
А вообще, стоит осознать простую мысль — в яваскрипте нет классов, всё — объекты и язык не ОО в классическом понимании. Даже функции — объекты. А метод — это обычная функция, просто если функцию вызвать вот таким способом obj.meth() внутри неё значению this будет присвоен obj.
Соответственно и дизайнить программу по другому можно.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Lazy Cjow Rhrr, Вы писали: LCR>Как я уже успел узнать, классы в js можно эмулировать кучей различных способов, один извращённее другого.
Я вот не уверен, что классы в джаваскрипт вообще нужны. Совершенно непонятно, зачем что-то эмулировать. Как правило, это всего лишь отражение дурной привычки к одному языку программирования. Имхо, лучше изучить натуральные для JS методики программирования.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
<code>
Спасибо, теперь есть из чего выбрать
.>А вообще, стоит осознать простую мысль — в яваскрипте нет классов, всё — объекты и язык не ОО в классическом понимании.
Ну это как раз понятно. Я ведь в первом посте и сказал про эмуляцию классов, а не про определение классов. Динамическое изменение сигнатуры объекта как раз должно мне пригодиться...
Sinclair,
LCR>>Как я уже успел узнать, классы в js можно эмулировать кучей различных способов, один извращённее другого. S>Я вот не уверен, что классы в джаваскрипт вообще нужны. Совершенно непонятно, зачем что-то эмулировать. Как правило, это всего лишь отражение дурной привычки к одному языку программирования.
В данном случае мне так удобнее.
S>Имхо, лучше изучить натуральные для JS методики программирования.
Динамическая типизация и интерпретируемость не отменяет необходимости в пользовательских типах данных, операциях над этими данными, ограничении области видимости имён и тому подобных вещах.
Натуральные...
Ты имеешь ввиду например
(function(){
for (var i; i<n; i++) {
var j;
}
})();
для того, чтобы переменные i и j не вылазили за блок?
Или например
function attach()
{
var element = document.getElementById("my-element");
element.attachEvent("onclick", function()
{
alert("Clicked: " + this.innerHTML);
}.closure(element));
}
где closure определён как
Function.prototype.closure = function(obj)
{
// Init object storage.
if (!window.__objs)
{
window.__objs = [];
window.__funs = [];
}
// For symmetry and clarity.
var fun = this;
// Make sure the object has an id and is stored in the object store.
var objId = obj.__objId;
if (!objId)
__objs[objId = obj.__objId = __objs.length] = obj;
// Make sure the function has an id and is stored in the function store.
var funId = fun.__funId;
if (!funId)
__funs[funId = fun.__funId = __funs.length] = fun;
// Init closure storage.
if (!obj.__closures)
obj.__closures = [];
// See if we previously created a closure for this object/function pair.
var closure = obj.__closures[funId];
if (closure)
return closure;
// Clear references to keep them out of the closure scope.
obj = null;
fun = null;
// Create the closure, store in cache and return result.
return __objs[objId].__closures[funId] = function ()
{
return __funs[funId].apply(__objs[objId], arguments);
};
};
чтобы пресечь мемори лики?
Ещё вот я сейчас читаю про пространства имён в javascript. Натуральнее просто некуда.
Или чего ты имел ввиду под словосочетанием "натуральные методики"?
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Я имел ввиду что мешает не создавать множество одинаковых анонимных функций для каждого метода.
да ничто не мешает, кроме того что вы их таки создаете )
есть еще такой вариант:
function MyClass(config) {
config=(config)?config:MyClass.get_methods_config();
this.obj_name='MyClass';
for(var method_name in config) this[method_name]=config[method_name];
}
MyClass.get_methods_config=function() {
var result={};
config['method1']=function() { alert(this.obj_name+' method 1 call.'); };
config['method2']=function() { alert(this.obj_name+' method 2 call.'); };
config['method3']=function() { alert(this.obj_name+' method 3 call.'); };
}
...
var cnf=MyClass.get_methods_config();
var obj_arr=new Array();
for (var i=0;i<100;i++) {
obj_arr[i]=new MyClass(cnf);
}
var obj=obj_arr[5];
obj.method2();
в таком случае набор методов будет создаваться единожды и тормозов при создании кучи объектов данного класса не будет.
и this внутри методов будет работать верно.
я уже несколько раз писал свою эмуляцию — вот еще раз
function Class(parent,ctor,impl)
{
var _link = function(){};
_link.prototype=parent.prototype;
ctor.prototype=new _link();
impl.call(ctor.prototype, parent.prototype, ctor); // есть вопрос насчет правильности второго параметра в тех случаях что использую я - все ок.
ctor.prototype.constructor=ctor; /* это не обязательно, но для порядка пусть будет*/
return ctor;
}
дальше пример+тест для вызова из консоли
$ = function( p )
{
WScript.StdOut.WriteLine(p)
}
A = Class( /*базовый класс*/Object,
/*конструктор*/
function()
{
$("A()");
},
/*методы и т.п
_base для вызова базовых методов
_static для создания статических полей - т.е в примере будет доступно через A.testEnum
this для создания методов в прототипе
переменные + замыкания для создания private членов
*/
function( _base, _static )
{
_static.testEnum = { One:1, Two:2 };
this.foo = function()
{
$( "A.foo" );
}
var some = 0; // private
this.setSome = function( v ){ some = v; }
this.getSome = function(){ return some; }
});
B = Class( A,
function()
{
A.call(this); // вызов конструктора предка. вручную через имя, можно сделать автоматически в Class() но тогда нет возможности упралять передачей параметров.
$("B()");
},
function( _base, _static )
{
this.foo = function()
{
$("B.foo");
_base.foo.call(this); // вызов базовой функции
}
});
function main()
{
var o = new B();
$(o instanceof B);
$(o instanceof A);
o.foo();
$(A.testEnum.Two);
o.setSome( 10 );
$( o.getSome() );
}
main();
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Натуральные... LCR>Ты имеешь ввиду например LCR>[...] LCR>для того, чтобы переменные i и j не вылазили за блок?
В этом нет ничего страшного, нужно просто помнить об этом. Тот же Pascal ведёт себя аналогичным образом, правдя там переменные в одлном месте определяются. Не C единым.
LCR>Или например LCR>[...] LCR>чтобы пресечь мемори лики?
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Lazy Cjow Rhrr, Вы писали: LCR>>Как я уже успел узнать, классы в js можно эмулировать кучей различных способов, один извращённее другого. S>Я вот не уверен, что классы в джаваскрипт вообще нужны.
Тем не менее в ES4/JS2 они есть. Мотивировка: Для больших проектов классы удобнее.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Lazy Cjow Rhrr, Вы писали: LCR>>Как я уже успел узнать, классы в js можно эмулировать кучей различных способов, один извращённее другого. S>Я вот не уверен, что классы в джаваскрипт вообще нужны. Совершенно непонятно, зачем что-то эмулировать.
Эмуляция классов позволяет строить решения по паттернам проектирования. Меня лично это пару раз выручало.
Здравствуйте, MasterMind, Вы писали: MM>Эмуляция классов позволяет строить решения по паттернам проектирования. Меня лично это пару раз выручало.
Гм. На всякий случай напомню, что "паттерны проектирования" специфичны для некоторой парадигмы. Сейчас наиболее известны паттерны ООП, поэтому неудивительно, что тебе пришлось эмулировать classic OOP для их использования.
Я бы всё же предпочел конкретные случаи, в которых тебя выручала эмуляция. Просто чтобы посмотреть, нет ли более другого способа.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Я бы всё же предпочел конкретные случаи, в которых тебя выручала эмуляция. Просто чтобы посмотреть, нет ли более другого способа.
всегда есть другие способы.
но самая короткая дорога — известная дорога.
если человек хочет и умеет писать на классах и на наследованиях, это его право
Здравствуйте, _pk_sly, Sinclair, Вы писали:
S>>Я бы всё же предпочел конкретные случаи, в которых тебя выручала эмуляция. Просто чтобы посмотреть, нет ли более другого способа. __>всегда есть другие способы. __>но самая короткая дорога — известная дорога. __>если человек хочет и умеет писать на классах и на наследованиях, это его право
я вообще не понимаю, о чем тут спор
эмуляция того, эмуляция сего...
если начать с того, что понятие "эмулированности классов" зависит от вашего личного определения понятия "классы".
для кого-то класс — это просто шаблон объекта, а для кого-то он еще должен соответствовать всем постулатам ООП, при чем полностью, т.е. не только поддерживать наследование, но и приватность/публичность членов и еще кучу всего.
а если еще вспомнить, что по используемым в этой ветке критериям вообще все скриптовые языки априори являются "эмуляциями", так вообще — о чем тут говорить?
DSD>я вообще не понимаю, о чем тут спор DSD>эмуляция того, эмуляция сего... DSD>если начать с того, что понятие "эмулированности классов" зависит от вашего личного определения понятия "классы". DSD>для кого-то класс — это просто шаблон объекта, а для кого-то он еще должен соответствовать всем постулатам ООП, при чем полностью, т.е. не только поддерживать наследование, но и приватность/публичность членов и еще кучу всего
Как-то однажды знаменитый учитель Кх Ан вышел на прогулку со учеником Антоном. Надеясь разговорить учителя, Антон спросил: "Учитель, слыхал я, что объекты — очень хорошая штука — правда ли это?" Кх Ан посмотрел на ученика с жалостью в глазах и ответил: "Глупый ученик! Объекты — всего лишь замыкания для бедных."
Пристыженный Антон простился с учителем и вернулся в свою комнату, горя желанием как можно скорее изучить замыкания. Он внимательно прочитал все статьи из серии "Lambda: The Ultimate", и родственные им статьи, и написал небольшой интерпретатор Scheme с объектно-ориентированной системой, основанной на замыканиях. Он многому научился, и с нетерпением ждал случая сообщить учителю о своих успехах.
Во время следующей прогулки с Кх Аном, Антон, пытаясь произвести хорошее впечатление, сказал: "Учитель, я прилежно изучил этот вопрос, и понимаю теперь, что объекты — воистину замыкания для бедных." Кх Ан в ответ ударил Антона палкой и воскликнул: "Когда же ты чему-то научишься? Замыкания — это объекты для бедных!" В эту секунду Антон обрел просветление.
Здравствуйте, DSD, Вы писали:
DSD>P.S. а то чейта чую ХолиВор намечается
не вижу темы для холивора.
человек привык работать в определённом фреймворке, с определённой объектной системой. не важно как её назвать: ООП, настоящяя ООП, реально настоящая ООП или ещё как.
Здравствуйте, _pk_sly, Вы писали:
__>человек привык работать в определённом фреймворке, с определённой объектной системой. не важно как её назвать: ООП, настоящяя ООП, реально настоящая ООП или ещё как. __>он реальзовал её себе на JS и работает с ней.
так я, собственно, о том же. и, отвечая именно на ваше сообщение, я вовсе не становился тем самым в оппозицию. наоборот, всячески поддерживаю вашу точку зрения. просто ответил в конец подветки.
а хотел сказать я своим сообщением, что не очень понимаю категоричности заявления "в JS нет классов". вот и все
Здравствуйте, DSD, Вы писали:
DSD>а хотел сказать я своим сообщением, что не очень понимаю категоричности заявления "в JS нет классов". вот и все
Категоричное утверждение видимо ближе всего к тому, что есть на самом деле. Иначе бы нас всех забросали менее категоричными, но частными смыслами в стиле "в JS классы есть в том смысле, как лично я это понимаю, то есть не то, чтобы в целом, а как бы вот сбоку, с точки зрения э... некого шаблона, как я его себе представляю...". Какая-то польза от рассмотрения данных смыслов есть, но всё-таки это некое знание второго или десятого уровня, на первом же базовом уровне нужны базовые знания — стандарт: "does not contain proper classes such as those in C++, Smalltalk, or Java". Прямолинейно и без затей. В том же тренде и многочисленные доки-спеки по javascript, играющие именно на противопоставлении — PBL vs. CBL, classes vs. constructors, наша терминология vs. чужеродная терминология, это много полезнее, чем чей-то частный около-классовый sugar...
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, MasterMind, Вы писали: MM>>Эмуляция классов позволяет строить решения по паттернам проектирования. Меня лично это пару раз выручало. S>Гм. На всякий случай напомню, что "паттерны проектирования" специфичны для некоторой парадигмы. Сейчас наиболее известны паттерны ООП, поэтому неудивительно, что тебе пришлось эмулировать classic OOP для их использования.
S>Я бы всё же предпочел конкретные случаи, в которых тебя выручала эмуляция. Просто чтобы посмотреть, нет ли более другого способа.
вот ещё до эпохи веб 2.0 я пытался в то время приспособить явасrрипт под свои задачи. понятное дело что можно найти решение лучше. observer
_JoKe_,
_JK>я уже несколько раз писал свою эмуляцию — вот еще раз _JK>
_JK>function Class(parent,ctor,impl)
_JK>{
_JK> var _link = function(){};
_JK> _link.prototype=parent.prototype;
_JK> ctor.prototype=new _link();
_JK> impl.call(ctor.prototype, parent.prototype, ctor); // есть вопрос насчет правильности второго параметра в тех случаях что использую я - все ок.
_JK> ctor.prototype.constructor=ctor; /* это не обязательно, но для порядка пусть будет*/
_JK> return ctor;
_JK>}
_JK>
Спасибо, интересно. Правдао из-за необходимости поддерживать наследование твоё решение выглядит как оверкилл. Мне не нужно наследование, поэтому я предпочёл бы решение попроще.