Comments 37
Люди, я тут — новенький, поэтому могу немного «косячить». Извиняюсь за «много букв», но статья по-моему завершена по своей структуре.
И ещё: я не знаю как, но очень хотелось бы перенести её в блог «Javascript»
И ещё: я не знаю как, но очень хотелось бы перенести её в блог «Javascript»
+4
что-то как-то все чересчур сложно )
Ext.override(Function, {
decorate: function(fPre, fPost) {
var _this = this;
return function () {
if (fPre) fPre.call(this, arguments);
var res = _this.apply(this, arguments);
if (fPost) fPost.call(this, res, arguments);
return res;
};
}
});
>>> var add = function (a, b) {return a+b;}
>>> add1 = add.decorate(function(args){console.info('function called with args:', args)}, function(res){console.info('end returned:',res)})
function()
>>> add1(2,5)
function called with args: [2, 5]
end returned: 7
7
0
Согласен, в чём-то у меня сложней, чем у ExtJS :)
Но во-первых, я излагал материал в развёрнутом виде, для читабельности.
А во-вторых, мой механизм является более универсальным:
вот смотрите, код Ext'а использует
Ну и в моём варианте я могу не просто «навешивать» вызовы «до» и «после», но и убирать их. И это не вызовет code mess.
Но во-первых, я излагал материал в развёрнутом виде, для читабельности.
А во-вторых, мой механизм является более универсальным:
вот смотрите, код Ext'а использует
_this
, который просто вызывается внутри декоратора. В то время, как мой декоратор имеет внутри себя ссылку на оригинальную ф-цию, что важно. Мой декоратор по сути полностью «оборачивает» исходную ф-цию, и манипулирует ей внутри себя как хочет. В то время, как Ext-овский вариант просто добавляет вызовы «до» и «после».Ну и в моём варианте я могу не просто «навешивать» вызовы «до» и «после», но и убирать их. И это не вызовет code mess.
0
дело не в Ext, это просто сокращенная запись
Function.prototype.decorate = function () ...
0
А, вы про сам Ext.override?
Так ведь приведённый мой Function.method(...) — в точности то же самое, только аргументы передаются не Object'ом, как в Ext.override, а именнем+значением.
Так ведь приведённый мой Function.method(...) — в точности то же самое, только аргументы передаются не Object'ом, как в Ext.override, а именнем+значением.
0
ну остальной код я сам придумал, а не взял из Ext )
0
то есть, если точнее, то когда-то нагуглил кажется тут szeged2008.drupalcon.org/files/JS%20components.pdf
0
А, вот оно что :)
В зачатках мой код был очень похож на ваш. Но чем дальше в лес, тем толще партизаны.
Я глянул одним глазом на реализацию декораторов в Python, и понял, что внутри декоратора должен быть доступ к оригинальной ф-ции.
Глянул в тот же Ext, на объект Observable, и понял, что необходимо иметь addListener и removeListener.
Ну и идея пошла дальше Ж)
В зачатках мой код был очень похож на ваш. Но чем дальше в лес, тем толще партизаны.
Я глянул одним глазом на реализацию декораторов в Python, и понял, что внутри декоратора должен быть доступ к оригинальной ф-ции.
Глянул в тот же Ext, на объект Observable, и понял, что необходимо иметь addListener и removeListener.
Ну и идея пошла дальше Ж)
0
Да, и моя реализация before('smth', ...) — может отменить выполнение основной ф-ции )
0
Отличная вещь.
С помощью этого можно трекать вызовы в браузерах, где нету нормальных JS отладчиков. Хотя, помоему, автор задумывал её для другого :)
С помощью этого можно трекать вызовы в браузерах, где нету нормальных JS отладчиков. Хотя, помоему, автор задумывал её для другого :)
0
Ели честно, то ноги у идеи растут именно оттуда, откуда вы сказали :)
Мне надо было сделать debug вызова некоторых ф-ций в IE. Можно, конечно, просто «остановить» поток коммандой debugger. Но что если в браузере нет отладчика, или нет доступа к исходному коду?
Вообщем, если эта статья народу понравится, я мог бы подумать над применениями моего кода.
Собственно, можете предлагать, а я смогу это учесть :)
Мне надо было сделать debug вызова некоторых ф-ций в IE. Можно, конечно, просто «остановить» поток коммандой debugger. Но что если в браузере нет отладчика, или нет доступа к исходному коду?
Вообщем, если эта статья народу понравится, я мог бы подумать над применениями моего кода.
Собственно, можете предлагать, а я смогу это учесть :)
0
Про исходный код вы что-то не то говорите. В чужом можно точки остановки ставить.
0
Можно. Но что, если у вас нет возможности их ставить? Например, у вас — Internet Explorer 6, без script debugger-плагина. Или Opera 8.5
0
Вот и я про то же. Если есть дебаггер, то нет проблемы доступа к исходному коду. В любом другом случае, если нет доступа к исходному коду и нет дебаггера, то ваш метод тоже не поможет.
0
Ну, ключевое слово debugger может ничего и не даст, если отсутствует хоть какой-то debugger. Однако в любом браузере можно написать нечто следующее:
прямо в адресной строке любого браузера. Так и дебажить, простым
javascript:f=function(x){alert(x)};f=f.decorate(function(x){alert('decorator: '+x); arguments.callee.old.apply(this, arguments)});f(5);
* This source code was highlighted with Source Code Highlighter.
прямо в адресной строке любого браузера. Так и дебажить, простым
alert()
:-) 0
Отличная статья. Не без недочетов, но тем не менее, плюс и топику, и в карму.
Недостатки (имхо):
1) Изменение базовых объектов (Function, Array, Object, etc.) — порочная практика.
Пример:
Вот вы объявили метод Function.prototype.method, который расчитывает, что к нему данные придут в порядке «имя нового метода», function. А кто-то другой написал метод с таким же названием, только ожидает данных в обратном порядке. Вам и этому кому-то все равно — вы-то разберетесь, что происходит. А кто-нибудь третий, подключив и ваш, и чужой код, оба ваших кода, получит кашу, и будет не знать, куда бежать.
2) Путица вида «класс, класс Function, ой, в Javascript нет классов» в пункте «Нырнем на пару метров вглубь». Лучше бы определиться.
Недостатки (имхо):
1) Изменение базовых объектов (Function, Array, Object, etc.) — порочная практика.
Пример:
Вот вы объявили метод Function.prototype.method, который расчитывает, что к нему данные придут в порядке «имя нового метода», function. А кто-то другой написал метод с таким же названием, только ожидает данных в обратном порядке. Вам и этому кому-то все равно — вы-то разберетесь, что происходит. А кто-нибудь третий, подключив и ваш, и чужой код, оба ваших кода, получит кашу, и будет не знать, куда бежать.
2) Путица вида «класс, класс Function, ой, в Javascript нет классов» в пункте «Нырнем на пару метров вглубь». Лучше бы определиться.
+1
>> 1) Изменение базовых объектов (Function, Array, Object, etc.) — порочная практика.
Совершенно согласен. Но всё-таки
>> 2) Путица вида «класс, класс Function, ой, в Javascript нет классов» в пункте «Нырнем на пару метров вглубь». Лучше бы определиться.
Извиняюсь, мне просто было удобно использовать слово «класс». Википедия пишет так:
Javascript uses prototypes instead of classes for defining object properties, including methods, and inheritance. It is possible to simulate many class-based features with prototypes in Javascript.
А значит классов здесь никаких нет :)
Совершенно согласен. Но всё-таки
Function.method
, Function.decorate
и Function.restore
— красиво. От остального можно избавиться.>> 2) Путица вида «класс, класс Function, ой, в Javascript нет классов» в пункте «Нырнем на пару метров вглубь». Лучше бы определиться.
Извиняюсь, мне просто было удобно использовать слово «класс». Википедия пишет так:
Javascript uses prototypes instead of classes for defining object properties, including methods, and inheritance. It is possible to simulate many class-based features with prototypes in Javascript.
А значит классов здесь никаких нет :)
0
Вы со словом «класс» создаёте сильную путаницу в тексте. Даже если отвлечься от того, что в JS нет классов, саму по себе функцию (Object, Function, YourClassName) обычно не называют классом, а называют конструктором класса. Сам класс — это нечто более абстрактное: совокупность конструктора, его прототипа и всяких других вещей.
+2
Ну хорошо, в будущем я постараюсь не использовать слово "класс" в контексте Javascript :)
Я навёл справки в документации ECMA-262: там используются следующие термины для функций:
1) Метод — функция, хранимая в свойстве объекта.
2) Конструктор — объект типа Function, который создаёт и инициализирует объекты.
3) А также функцию можно называть объектом типа
Заметьте: просто конструктор, но не конструктор класса, и это принципиально.
Почитать ещё можно тут: http://javascript.ru/ecma/part4
Я навёл справки в документации ECMA-262: там используются следующие термины для функций:
1) Метод — функция, хранимая в свойстве объекта.
2) Конструктор — объект типа Function, который создаёт и инициализирует объекты.
3) А также функцию можно называть объектом типа
Function
.Заметьте: просто конструктор, но не конструктор класса, и это принципиально.
Почитать ещё можно тут: http://javascript.ru/ecma/part4
+1
У вас какая-то путаница образовалась. В коде функции strictArgs вы пишете «var types = arguments», а в пояснении ниже «var types = [].slice.apply(arguments)».
0
Спасибо, что заметили. Сначала я использовал [].slice.apply(arguments), но потом подумал, что это излишне, и заменил на просто
arguments
. Но получается, что заменил не везде :-) Я это исправил. +1
Нет там путаницы. Это аргументы разных функций (обратите внимание на то что возвращается тоже ф-ция)
0
UFO just landed and posted this here
Раз уж вы дали здесь рекламу своего фреймворка Ajaxpect, напишу на него свою небольшую критику :-)
Я почитал ваш код и выделю следующее:
Плюсы:
1) Отвязанность от прототипов стандартных объектов, вроде
2)Продвинутый и довольно удобный поиск методов в объекте:
* можно задать имя метода
* можно задать функцию-фильтр, которая возвращает
* можно задать RegExp, который также фильтрует имена методов объекта
Теперь минусы:
1) Самое плохое — нет возможности снять навешенный декоратор. Сейчас у вас это можно сделать только внутри самого декоратора, но довольно хитро. А если навесить декоратор дважды, то такая возможность и вовсе исчезнет.
2) Само разделение методов
*
*
Это основное, что я заметил.
Теперь давайте сравним с моим творением — у меня всё с точностью до наоборот:
Минусы:
1) Я «засорил» стандартный объект
2) У меня самый простой способ поиска метода: по имени.
3) Да, и у меня нет в явном виде вашего
Но плюсы:
1) Есть
2) «Хорошая» организация стэка listener'ов
3) «Хорошая» реализация
По мощности моя реализация равна вашей. но я бы вам советовал разложить всё по полочкам и учесть мои замечания. К тому же, я написал эту статью в ознакомительных целях. По сути мой код можно оформить в отдельный framework, но я пока не хочу этого делать :-)
Я почитал ваш код и выделю следующее:
Плюсы:
1) Отвязанность от прототипов стандартных объектов, вроде
Object
и Function
(всё делается через объект Ajaxpect)2)Продвинутый и довольно удобный поиск методов в объекте:
* можно задать имя метода
* можно задать функцию-фильтр, которая возвращает
true
, если переданное в неё имя метода соответствует неким условиям* можно задать RegExp, который также фильтрует имена методов объекта
Теперь минусы:
1) Самое плохое — нет возможности снять навешенный декоратор. Сейчас у вас это можно сделать только внутри самого декоратора, но довольно хитро. А если навесить декоратор дважды, то такая возможность и вовсе исчезнет.
2) Само разделение методов
addBefore
, addAfter
и addAround
— недоработано. К примеру:*
addAfter
легко выкидывается и реализуется через addAround
, т.к. вы передаёте в декоратор и оригинальную ф-цию, и её аргументы*
addBefore
— вы сначала выполняете функцию-декоратор, которая по сути возвращает изменённые arguments
в оригинальную ф-цию, и тут же вызываете оригинальную ф-цию. Декоратор «before» должен иметь возможность остановить выполнение оригинальной ф-ции.Это основное, что я заметил.
Теперь давайте сравним с моим творением — у меня всё с точностью до наоборот:
Минусы:
1) Я «засорил» стандартный объект
Function
.2) У меня самый простой способ поиска метода: по имени.
3) Да, и у меня нет в явном виде вашего
addAround
. Но он легко реализуем у меня через Function.decorate(...)
.Но плюсы:
1) Есть
removeBefore(...)
и removeAfter(...)
. 2) «Хорошая» организация стэка listener'ов
3) «Хорошая» реализация
addBefore
: если хоть один из addBefore-listener
'ов возвращает false
, оригинальная ф-ция не выполнится.По мощности моя реализация равна вашей. но я бы вам советовал разложить всё по полочкам и учесть мои замечания. К тому же, я написал эту статью в ознакомительных целях. По сути мой код можно оформить в отдельный framework, но я пока не хочу этого делать :-)
+1
Класс! С помощь вашего метода можно реализовать аспектно-ориентированный подход для Javascript.
0
UFO just landed and posted this here
статья потрясная! узнал новые вещи про js. очень полезно!
0
чувак, ты крут…
очень интересная статья, спасибо
ЗЫ Javascript меня не перестает удивлять…
очень интересная статья, спасибо
ЗЫ Javascript меня не перестает удивлять…
0
Sign up to leave a comment.
Слушаем вызовы функций в Javascript