Interception of function calls
Many here tried to override .call. Some of them failed, some succeeded. I answer this old question since it was raised at my workplace, and this post is used as a link.
Only two functions related to functions are available for us: we can change: .call and .apply. I will demonstrate successful redefinition of both.
TL DR: what the OP asks is impossible. Some of the success reports in the responses are due to the console calling .call internally just before the evaluation, and not because of the call we want to intercept.
Overriding the .prototype.call function
This seems to be the first idea that people came up with. Some of them were more successful than others, but here is an implementation that works:
// Store the original var origCall = Function.prototype.call; Function.prototype.call = function () { // If console.log is allowed to stringify by itself, it will // call .call 9 gajillion times. Therefore, lets do it by ourselves. console.log("Calling", Function.prototype.toString.apply(this, []), "with:", Array.prototype.slice.apply(arguments, [1]).toString() ); // A trace, for fun console.trace.apply(console, []); // The call. Apply is the only way we can pass all arguments, so don't touch that! origCall.apply(this, arguments); };
This successfully hooks the .prototype.call function
Take it for a spin, will we?
// Some tests console.log("1"); // Does not show up console.log.apply(console,["2"]); // Does not show up console.log.call(console, "3"); // BINGO!
It is important that this does not start from the console. Different browsers have all kinds of console tools that very often call .call, including once for each login, which can frighten the user at the moment. Another mistake is simply the console.log arguments that go through the api console for stringing, which in turn causes an infinite loop.
Overriding the .prototype.apply function also
Well, how then to apply? They are the only magical calling functions we have, so let's try this. Here comes the version that catches both:
// Store apply and call var origApply = Function.prototype.apply; var origCall = Function.prototype.call; // We need to be able to apply the original functions, so we need // to restore the apply locally on both, including the apply itself. origApply.apply = origApply; origCall.apply = origApply; // Some utility functions we want to work Function.prototype.toString.apply = origApply; Array.prototype.slice.apply = origApply; console.trace.apply = origApply; function logCall(t, a) { // If console.log is allowed to stringify by itself, it will // call .call 9 gajillion times. Therefore, do it ourselves. console.log("Calling", Function.prototype.toString.apply(t, []), "with:", Array.prototype.slice.apply(a, [1]).toString() ); console.trace.apply(console, []); } Function.prototype.call = function () { logCall(this, arguments); origCall.apply(this, arguments); }; Function.prototype.apply = function () { logCall(this, arguments); origApply.apply(this, arguments); }
... and try to try!
// Some tests console.log("1"); // Passes by unseen console.log.apply(console,["2"]); // Caught console.log.call(console, "3"); // Caught
As you can see, the calling bracket goes unnoticed.
Conclusion
Fortunately, calling brackets cannot be intercepted using JavaScript. But even if .call intercepts the parenthesis operator on function objects, how could we call the original without calling an infinite loop?
The only thing that overrides .call / .apply is intercepting the explicit calls of these prototypes. If the console is used with this hack in place, there will be a lot and a lot of spam. In addition, you must be very careful if it is used, since using the console API can quickly cause an infinite loop (console.log will use .call inside if it gives it a non-string).