Function.prototype.bind
function bind(context:Object[, arg1, ..., argN]):Function {
return a callback able to execute this function
passing context as reference via this
}
In few words, if we have a generic object, we don't necessary need to attach a function to create a method:
// a generic function
function name(name) {
if (name == null) return this.name;
this.name = name;
return this;
}
// a generic object
var wr = {name:"WebReflection"};
// a callback with a "trapped" object
var fn = name.bind(wr);
alert([
// wr has not been affected
wr.name, // WebReflection
// fn can always be called
fn(), // WebReflection
fn("test") === wr, // true
fn(), // test
wr.name // test
].join("\n"));
Designed to ensure the same context whatever way we decide to use the callback, included call, apply, setTimeout, DOM events, etc, Function.prototype.bind is one of the most useful/powerful JavaScript concept.
Unfortunately, this will be standard only with newer browser ...
Optimized bind for every browser
Update: as I have said I code what I need, I rarely google for simple tasks like this. Most of this code, in any case, has been readapted and tested to reach best performances, based on this proposal.
if (Function.prototype.bind == null) {
Function.prototype.bind = (function (slice){
// (C) WebReflection - Mit Style License
function bind(context) {
var self = this; // "trapped" function reference
// only if there is more than an argument
// we are interested into more complex operations
// this will speed up common bind creation
// avoiding useless slices over arguments
if (1 < arguments.length) {
// extra arguments to send by default
var $arguments = slice.call(arguments, 1);
return function () {
return self.apply(
context,
// thanks @kangax for this suggestion
arguments.length ?
// concat arguments with those received
$arguments.concat(slice.call(arguments)) :
// send just arguments, no concat, no slice
$arguments
);
};
}
// optimized callback
return function () {
// speed up when function is called without arguments
return arguments.length ? self.apply(context, arguments) : self.call(context);
};
}
// the named function
return bind;
}(Array.prototype.slice));
}
Why Bother
The concatenation optimization is something rarely present in whatever framework/library I have seen. While it makes the code a bit bigger than usual, performances will be the best for most common cases, those where optional arguments are not passed at all.A simple test case, one of my favorites, able to solve the classic IE problem with extra arguments passed to setInterval/Timeout:
(function(){
var callback = function(time){
if (1000 < new Date - time)
return alert("1 second with a default argument");
setTimeout(callback, 15);
}.bind(null, new Date);
setTimeout(callback, 15);
}());
No comments:
Post a Comment