Событие вызова функции
Чисто из интереса, решил узнать, можно ли повесить событие на вызов функции. Как ни странно (для меня), это удалось.
(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, время: 15:44. |