Monkey patching is a technique that can be used run some code before or after a function. You replace a function with a custom function that runs some code before and or after calling the original function and returns the value of the original function. The following example is a function that is able to patch other functions to log each call.
function log(f) {
return function (...args) {
const result = f.apply(this, args);
console.log(`${f.name}(${args.join(", ")}) = ${result}`);
return result;
};
}
function fibonacci(n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
fibonacci = log(fibonacci);
fibonacci(5);
There a few common gotchas that you need to pay attention when implementing a patch like this. We don't know much about the original function, it could be that the original function was meant to be called as a method of some class. For example, obj.f(). In this case, the function f is expecting the value of this to be obj. We need to preserve this behavior and that is why the function f is called with f.apply(this, args) instead of a direct call like f(...args). This way we avoid issues when f depends on where it is called from.
Since the global variables in JavaScript like the fetch function can be replaced, you can use this technique to help in debugging. For example, you can print all the calls that are being made to fetch. Another use case is when developing frameworks when you want to add custom behaviors to regular functions. For example, in the past, in Angular, the set timeout method was patched to re-render the components after a timeout happened.
window.setTimeout = log(setTimeout);
This is how you would patch the set timeout function. The window object in JavaScript holds all global variables and usually those properties are writable, meaning that you can modify the value. Future calls of setTimeout would be logged in this case.
Note that this technique shouldn't be used often, and this ability to modify globals, specially the builtin functions can cause compatibility problems in applications. It was mainly left in the language to be compatible with older software and new properties of the language are not added as writable anymore.