underscore.js has a really neat method called bind that does something quite interesting. Let me first talk you through what that method is addressing.
One of the foibles in JavaScript is that the this pointer has a somewhat unusual behaviour in that it will point to the window object, when inside a nested function. Take the following example:
var car = {
engine: 1,
doorToWheelRatio: function (nrOfDoors){
this.nrOfDoors = nrOfDoors;
return function (nrWheels) {
// 'this' refers to window object in here
return this.nrOfDoors / nrWheels;
};
}
};
There are two instances of this. The second one being in the nested function. That function is not going to behave as expected because the this pointer is pointing to the window object. This is a known foible, especially in light of the fact that the previous this pointer points at the car object.
The historical way in which developers have overcome that is to assign the this pointer to another variable in the enclosing function (e.g. self), thus making it available in the nested function:
var car = {
engine: 1,
doorToWheelRatio: function(nrOfDoors) {
this.nrOfDoors = nrOfDoors;
var self = this;
return function(nrWheels) {
return self.nrOfDoors / nrWheels;
};
}
};
Using underscore.js’ bind function, we can effortlessly bind the this pointer in that nested function to the car object:
var car = {
engine: 1,
doorToWheelRatio: function (nrOfDoors){
this.nrOfDoors = nrOfDoors;
return _.bind(function (nrWheels) {
return this.nrOfDoors / nrWheels;
}, car);
}
};
Now both instances of this are pointing at the same object, car.
When I say effortlessly, bear in mind it comes at substantial cost. Take a look at this benchmark which I have performed at perf.com which clearly shows that using bind is an expensive operation compared with using a local variable (as was historically done).
It would be remiss of me not to point out that jQuery also has an equivalent function called proxy. That code would look like the following if we were to use proxy:
var car = {
engine: 1,
doorToWheelRatio: function (nrOfDoors){
this.nrOfDoors = nrOfDoors;
return $.proxy(function (nrWheels) {
return this.nrOfDoors / nrWheels;
}, car);
}
};
That is all.
0 Comments.