Событие вызова функции
Чисто из интереса, решил узнать, можно ли повесить событие на вызов функции. Как ни странно (для меня), это удалось.
(function(){
window.callEvent = function(func, callback){
var callNumber = 0;
return function(){
var args = [].slice.call(arguments);
var result;
try {
result = func.apply(this, arguments);
callNumber++;
} catch (e) {
callback(e, args, this, callNumber);
throw e;
}
callback(result, args, this, callNumber);
return result;
}
}
var logSomething = function(something){
console.log(something);
}
logSomething = callEvent(logSomething, function(result, args, self, callNumber){
console.log('alertSomething has been called. \n\
Result is ' + result + '. \n\
Arguments are ' + args + '. \n\
Self is ' + self + '. \n\
Number of calls ' + callNumber + '. \n'
);
});
Array.prototype.push = callEvent(Array.prototype.push, function(result, args, self, callNumber){
console.log('Array.prototype.push has been called. \n\
Result is ' + result + '. \n\
Arguments are ' + args + '. \n\
Self is ' + self);
});
logSomething('Fuck yeah!');
logSomething('Fuck yeah!');
logSomething('Fuck yeah!');
logSomething('Fuck yeah!');
logSomething('Fuck yeah!');
var array = [1,2,3,4,5];
array.push(6);
})();
|
Цитата:
|
B@rmaley.e><e, точно, спасибо.
|
Только вот не могу придумать, как это сделать через Function.prototype.
|
а ну-ка, выкинь исключение в наблюдаемой функции))))
|
Не совсем понимаю о чем ты. Кинул исключение, всё остановилось. И что?
|
Цитата:
|
Цитата:
Function.prototype.callEvent = function(callback){
this = function(){...
Выкидывает исключение. |
Цитата:
|
Цитата:
|
Цитата:
Я бы, в данном случае поймал бы исключение, предал бы в обработчик события, и затем передал бы его дальше, наверх |
Цитата:
window.callEvent = function(func, callback){
return function(){
var args = Array.prototype.slice.call(arguments);
var result;
try {
result = func.apply(this, arguments);
} catch (e) {
result = e;
}
callback(result, args, this);
return result;
}
}
UPD Хотя нет, бред. |
Цитата:
|
Цитата:
window.callEvent = function(func, callback){
return function(){
var args = Array.prototype.slice.call(arguments);
var result;
try {
result = func.apply(this, arguments);
} catch (e) {
callback(e, args, this);
throw e;
}
callback(result, args, this);
return result;
}
}
|
Gvozd,
ок, спасибо. |
(не обновил страницу перед отправкой)
Цитата:
Цитата:
|
Цитата:
Да, и это просто спортивный интерес. Меня полгода назад спросили, можно ли ловить событие вызова какой-нибудь функции, я покрутил пальцем у виска и сказал "нет". Цитата:
Идея в том, что где-то определена функция или метод (даже встроенный, что было продемонстрировано на примере) и ты вешаешь обработчик (псевдообработчик) на её вызов. Я не знаю, как яснее выразиться. |
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
|
Цитата:
Но как минимум один раз обернуть придётся. |
можно было бы запилить с помощью __parent__, но это свойство уже склеило лыжи.
как вариант, можно переопределить функцию! |
Цитата:
|
Цитата:
весьма странный подход для дебага. |
Цитата:
|
trikadin, встроенные функции-то всё равно ручками оборачивать придётся.
|
Цитата:
|
Цитата:
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
f = function(){
...
}
f.attachCallListener(function{
...
})
f(); //а здесь уже вызывается функция и обработчик
Цитата:
А можешь, не меняя кода функции, посмотреть, сколько раз и как она вызывалась? Цитата:
Цитата:
|
А я бы сделал так:
window.callEvent = function(func, callback){
return function(){
var args = Array.prototype.slice.call(arguments);
var result;
try {
result = func.apply(this, arguments);
} catch (e) {
if(callback(e, args, this) !== false) throw e;
}
callback(result, args, this);
return result;
}
}
FINoM, Вам бы почитать про Proxy. v8 и SpiderMonkey вполне себе поддерживают. П.С. Вообще где то на хабре это уже было :) |
Цитата:
|
trikadin,
Кстати там в самом низу есть ссылки на презентацию Брендана Эйча. Сам ещё не смотрел, но надо бы посмотреть :) |
Цитата:
|
Цитата:
f = function(){
...
}
f.attachCallListener(function{
...
})
f(); //а здесь уже вызывается функция и обработчик
ты понимаешь, что attachCallListener надо вставить сразу же после определения f, иначе ты можешь пропустить вызов f? А это значит, что ну пусть ты не изменил код функции, но ты должен изменить код рядом с функцией. А о выносе в другой файл вообще речи не должно быть, по-крайней мере в данной абстрактной ситуации. Так что на практике ты к тому же усложняешь себе жизнь тем, что тебе надо думать, в каком месте можно обернуть функцию, чтобы ничего не пропустить. потом, даже если бы можно было сделать как ты хочешь, как бы это выглядело? Что-то типа jquery.live?
$('/js/script.js:1:f').live(function() {...});
Как указать вызов какой именно функции надо перехватывать? Цитата:
Цитата:
Цитата:
если же эта задача представляет академический, а не практический интерес, тогда у меня нету вопросов. Не вижу в этом ничего плохого. Но и интерес к ней у меня тогда автоматически пропадает. |
Цитата:
|
melky,
ага, стыдно ) |
Немного расширил функцию: теперь вместо одного колбека вторым аргументом передается объект
Форкнуть и потестить можно здесь: http://jsfiddle.net/finom/SGhzd/5/ |
| Часовой пояс GMT +3, время: 22:13. |