Ну всё, теперь можно искать «скрытые послания» во всех картинках в Инете :) Кстати, отличная идея — хранит ьсвои, скажем, самые секретные данные — в своих фотках на каком-то фотосайте. И запомнится легко — ассоциации с фоткой :)
Спасибо, полезная статья. С неё можно начать использовать Git и потихоньку уходить от SVN :-)
Хотя в своём интервью Линус Торвальдс говорил, что SVN продолжает отлично работать в большинстве проектов, но Git хорош в больших и сильно распределённых проектах.
Критиковал я Ajaxpect версии 0.9.0, скачал которую в 11:30 UTC time с code.google.com/p/ajaxpect/, чтобы потом на меня не наехали, что ничего такого в коде нет :)
Раз уж вы дали здесь рекламу своего фреймворка Ajaxpect, напишу на него свою небольшую критику :-)
Я почитал ваш код и выделю следующее: Плюсы: 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, но я пока не хочу этого делать :-)
Спасибо, что заметили. Сначала я использовал [].slice.apply(arguments), но потом подумал, что это излишне, и заменил на просто arguments. Но получается, что заменил не везде :-) Я это исправил.
Ну хорошо, в будущем я постараюсь не использовать слово "класс" в контексте Javascript :)
Я навёл справки в документации ECMA-262: там используются следующие термины для функций:
1) Метод — функция, хранимая в свойстве объекта.
2) Конструктор — объект типа Function, который создаёт и инициализирует объекты.
3) А также функцию можно называть объектом типа Function.
Заметьте: просто конструктор, но не конструктор класса, и это принципиально.
>> 1) Изменение базовых объектов (Function, Array, Object, etc.) — порочная практика.
Совершенно согласен. Но всё-таки 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.
А значит классов здесь никаких нет :)
Ели честно, то ноги у идеи растут именно оттуда, откуда вы сказали :)
Мне надо было сделать debug вызова некоторых ф-ций в IE. Можно, конечно, просто «остановить» поток коммандой debugger. Но что если в браузере нет отладчика, или нет доступа к исходному коду?
Вообщем, если эта статья народу понравится, я мог бы подумать над применениями моего кода.
Собственно, можете предлагать, а я смогу это учесть :)
Так ведь приведённый мой Function.method(...) — в точности то же самое, только аргументы передаются не Object'ом, как в Ext.override, а именнем+значением.
Но во-первых, я излагал материал в развёрнутом виде, для читабельности.
А во-вторых, мой механизм является более универсальным:
вот смотрите, код Ext'а использует _this, который просто вызывается внутри декоратора. В то время, как мой декоратор имеет внутри себя ссылку на оригинальную ф-цию, что важно. Мой декоратор по сути полностью «оборачивает» исходную ф-цию, и манипулирует ей внутри себя как хочет. В то время, как Ext-овский вариант просто добавляет вызовы «до» и «после».
Ну и в моём варианте я могу не просто «навешивать» вызовы «до» и «после», но и убирать их. И это не вызовет code mess.
Хотя в своём интервью Линус Торвальдс говорил, что SVN продолжает отлично работать в большинстве проектов, но Git хорош в больших и сильно распределённых проектах.
Так что надо пробовать, и самому делать выводы.
Я почитал ваш код и выделю следующее:
Плюсы:
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, но я пока не хочу этого делать :-)
arguments
. Но получается, что заменил не везде :-) Я это исправил.Я навёл справки в документации ECMA-262: там используются следующие термины для функций:
1) Метод — функция, хранимая в свойстве объекта.
2) Конструктор — объект типа Function, который создаёт и инициализирует объекты.
3) А также функцию можно называть объектом типа
Function
.Заметьте: просто конструктор, но не конструктор класса, и это принципиально.
Почитать ещё можно тут: http://javascript.ru/ecma/part4
прямо в адресной строке любого браузера. Так и дебажить, простым
alert()
:-)Совершенно согласен. Но всё-таки
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.
А значит классов здесь никаких нет :)
В зачатках мой код был очень похож на ваш. Но чем дальше в лес, тем толще партизаны.
Я глянул одним глазом на реализацию декораторов в Python, и понял, что внутри декоратора должен быть доступ к оригинальной ф-ции.
Глянул в тот же Ext, на объект Observable, и понял, что необходимо иметь addListener и removeListener.
Ну и идея пошла дальше Ж)
Мне надо было сделать debug вызова некоторых ф-ций в IE. Можно, конечно, просто «остановить» поток коммандой debugger. Но что если в браузере нет отладчика, или нет доступа к исходному коду?
Вообщем, если эта статья народу понравится, я мог бы подумать над применениями моего кода.
Собственно, можете предлагать, а я смогу это учесть :)
Так ведь приведённый мой Function.method(...) — в точности то же самое, только аргументы передаются не Object'ом, как в Ext.override, а именнем+значением.
Но во-первых, я излагал материал в развёрнутом виде, для читабельности.
А во-вторых, мой механизм является более универсальным:
вот смотрите, код Ext'а использует
_this
, который просто вызывается внутри декоратора. В то время, как мой декоратор имеет внутри себя ссылку на оригинальную ф-цию, что важно. Мой декоратор по сути полностью «оборачивает» исходную ф-цию, и манипулирует ей внутри себя как хочет. В то время, как Ext-овский вариант просто добавляет вызовы «до» и «после».Ну и в моём варианте я могу не просто «навешивать» вызовы «до» и «после», но и убирать их. И это не вызовет code mess.
И ещё: я не знаю как, но очень хотелось бы перенести её в блог «Javascript»