I just learned a new trick from my new colleague Adrian. When reviewing some of his code, I stumbled across this little function:
function bind(fnc, val) {
return function () {
return fnc(val);
};
}
What it does, is nothing more than building a closure. Something you could do manually using an anonymous function anyway.
However by introducing the additional wrapping function call it solves a problem very well described by Menno van Slooten. The problem is basically that variables are passed by reference to closures which will hurt you when a variable is reused inside a loop1).
Van Slooten presented his own solution, but Adrian's simple function turns this:
oListItem.onclick = function(value) {
return function() {
alert(value);
}
}(i);
into this2):
oListItem.onclick = bind(alert,i);
Much nicer, isn't it?
But what if you need to pass more than one argument to your function? Adrian came up with this:
function fix (fnc) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return fnc.apply(this, args);
}
}
Yes. Magic. Advanced magic
.
The function grabs all function arguments from the arguments
object3) and turns it into an array (skipping the function name itself). It then does what the simpler bind()
did above – it executes the function and passes the arguments.
This function will spare me a few headaches in the future for sure and will be added to the DokuWiki script library of course.