About six months ago, I was asked a question like this: “I use a large framework that runs a certain function according to the user's action. I want, without changing the code of this function, to execute my code on the event of calling this function. ”. The practice is far from the best, function call events do not exist, I just twisted my finger at my temple and said that this is a terrible govnokod, so it’s not worth doing, and this is simply not possible.
A couple of days ago, heading home for a relatively warm winter evening, not typical for Odessa, I had an atypical thought: “What if I tried to do what Bogdan asked six months ago?”. When I got home, I turned on the computer, and within a couple of minutes I did what I had in mind. First of all, I was interested in how the built-in methods behave, if they are redefined, and whether it is possible after that to somehow call their previous state, which was before the redefinition. I knew that if an object is redefined, then references to it will not be destroyed, keeping the same look. As for the built-in functions, there were doubts. It turns out you can.
Most likely, I will never even have to use such a tool, but, purely hypothetically, it is possible that someone will have the task to trace the call of a function, having received a report on each call, consisting of:
- The result of the execution
- Arguments passed
- Call context (what is this when called)
- The number of function calls after creating the handler
(This list fully corresponds to the arguments passed to the handler.)
addCallListener = 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; } }
')
Very simple and short, right?
Then, override any function as follows:
someFunct = addCallListener(someFunct, function(result, args, self, callNumber){
Obviously, it should be “visible” in the part of the code where it occurs.
A few examples
To run the examples, you must have an open console (in chrome, it is called by Ctrl + Shift + i).
Animation tracking:
jsfiddle.net/finom/DnRD8Push method execution event in array:
jsfiddle.net/finom/bbHhH/1Event of execution of some other function:
jsfiddle.net/finom/ah5My/3The End.
Thanks comrades from the forum javascript.ru for criticism and additions.
UPD
Slightly expanded the function: now instead of one callback, the second argument is an object
- before (called before the function starts)
- success (called if the function completed successfully)
- error (if an error occurred)
- after (called in any case, regardless of the success of the execution)
An object is passed to each handler.
- args
- self (context)
- name (function name)
- status ("error" or "success")
- successNumber (number of successful calls)
- errorNumber (the number of calls with an error)
- result (result if any)
- error (error if any)
In addition, the addCallListener function is now part of the Function constructor object, to avoid getting into a window or process.
Fork and potest can here:
jsfiddle.net/finom/SGhzd/5