Make functions "hookable" so you can pre-process their input and post-process their output...
Overview
The Hook API lets you turn an existing function in to a hookable function:
Make a function hookable
var myFn = function foo(a, b) {
return a + b;
}
myFn.canHook; // false
var myHookedFn = Hook(myFn);
myFn.canHook; // false
myHookedFn.canHook; // myFn (typecasts to true)
myHookedFn.canHook.name; // "foo"
myHookedFn.canHook.length; // 2 (myFn defines 2 formal parameters)
myHookedFn.name; // "hooked"
myHookedFn.length; // 0 (doesn't define formal parameters)
It's a bit like function.wraps(), in that the original function (eg. myFn) will be wrapped in a new function (eg. myHookedFn). The main difference is that once you've made a function hookable, you can add input and output hooks to it.
Input hooks
An input hook lets you alter the parameters (params) that will be sent to the inner function. The input parameters are:
params – an editable array of parameters that will be sent to the inner function
args – a read-only array of parameters that were used on the outer function
hooked – a reference to the outer function (get the inner function via hooked.canHook)
Continuing from the last example...
Create an input hook to change params
myHookedFn.onInput; // 0 (typecasts to false)
// catch the fish
myHookedFn.onInput = function(params, args, hooked) {
// play with it (note: arguments is immutable)
params[0] = 10; // a => 10
// throw it back in the river
return params;
}
myHookedFn.onInput; // 1 (typecasts to true)
myFn(1, 2); // 3 (1 + 2)
myHookedFn(1, 2); // returns 12 (10 + 2)
Remember to return the params array, otherwise the inner function won't be called.
Output hooks
An output hook lets you alter the functions return value.
The parameters are:
result – the editable result returned by the inner function
params – a read-only array of parameters that will be sent to the inner function
args – a read-only array of parameters that were used on the outer function
hooked – a reference to the outer function (get the inner function via hooked.canHook)