Javascript: Function Proxies
I’m sure you have sometimes felt the need of hooking to a function which code you have no access to, and you may have come to the conclusion that whether it's not possible, or it’s too hard to achieve to be worth the effort; well, proxy pattern (not to be confused with ES6 Proxy ) might be just what you need.
Proxies? Is that what I’m looking for?
There are endless possible scenarios so this might not provide you exactly what you need, although, proxies are your solution if:
-
Your intention is to interfere with the code of a foreign function that you are not able to modify like you would normally do.
-
You want to, besides of interfering, leave its default behavior intact.
Feeling identified? Still not sure? I'd suggest you to keep reading either way, if it fits your needs then awesome, problem solved; if it doesn't, then you might have found an useful resource to use in the future, and who knows, maybe while reading you find some new inspiration to solve your issue.
Sounds good, but also convoluted...
It's actually quite simple, more than you'd imagine, what if I said you could have a perfectly functional proxy ready with only six lines of code? As we all know there is no better way to convince someone than to prove it so there we go.
In this example we'll make a simple proxy to the native alert() function:
(function (proxied) {
window.alert = function (message) {
console.log("Alert called with the following message:", message);
return proxied.apply(this, arguments);
};
})(window.alert);
alert("Hello World");
As you may have guessed, what we achieve with this proxy is that when the alert() function is called, a console.log() function is also triggered with the text passed as argument, this way we managed to display the message in the console when the alert() function is called and the alert dialog still pops up as always.
But… what if I only want the default behavior in some situations?
Glad you asked, if you look at the proxy code you will see there is a return calling itself that's applied passing its arguments, this is what allows the default behavior to keep running after your code, in this example if you only want the dialog to pop up depending on the text argument you only have to surround this return by your condition, just as we did in the following example:
(function (proxied) {
window.alert = function (message) {
console.log("Alert called with the following message:", message);
if (message != "Vimlet") {
return proxied.apply(this, arguments);
}
};
})(window.alert);
alert("Vimlet");
Now the dialog will only appear when the argument is different from “Vimlet”.
Conclusion
As you can see there are many ways of taking advantage of proxies, you can just hook into practically any function to be aware of when it's being called, it can also be used to create polyfills of native functions having different behaviors in certain browsers, be aware though, you should be careful when playing with native functions, as it might have catastrophic consequences, and you don't want to be the one responsible.