Gotten from JavaScriptisSexy
You should read the JavaScript 201 and the Prototype explanation before you read this.
Functions are objects in JavaScript, as you should know by now, if you have read any of the prerequisite articles. And as objects, functions have methods, including the powerful Apply, Call, and Bind methods. On the one hand, Apply and Call are nearly identical and are frequently used in JavaScript for borrowing methods and for setting the this value explicitly. We also use Apply for variable-arity functions; you will learn more about this in a bit.
On the other hand, we use Bind for setting the this value in methods and for currying functions.
We will discuss every scenario in which we use these three methods in JavaScript. While Applyand Call come with ECMAScript 3 (available on IE 6, 7, 8, and modern browsers), ECMAScript 5 (available on only modern browsers) added the Bind method. These 3 Function methods are workhorses and sometimes you absolutely need one of them. Let’s begin with the Bind method.
JavaScript’s Bind Method
We use the Bind () method primarily to call a function with the this value set explicitly. It other words, bind () allows us to easily set which specific object will be bound to this when a function or method is invoked.
This might seem relatively trivial, but often the this value in methods and functions must be set explicitly when you need a specific object bound to the function’s this value.
The need for bind usually occurs when we use the this keyword in a method and we call that method from a receiver object; in such cases, sometimes this is not bound to the object that we expect it to be bound to, resulting in errors in our applications. Don’t worry if you don’t fully comprehend the preceding sentence. It will become clear like teardrop in a moment.
JavaScript’s Bind Allows Us to Set the this Value on Methods
When the button below is clicked, the text field is populated with a random name.
When you click the button, you get an error because this in the clickHandler () method is bound to the button HTML element, since that is the object that the clickHandler method is executed on.
This particular problem is quite common in JavaScript, and JavaScript frameworks like Backbone.js and libraries like jQuery automatically do the bindings for us, so that this is always bound to the object we expect it to be bound to.
To fix the problem in the preceding example, we can use the bind method thus:
Instead of this line:
We simply have to bind the clickHandler method to the user object like this:
Consider this other way to fix the this value: You can pass an anonymous callback function to the click () method and jQuery will bind this inside the anonymous function to the button object.
Because ECMAScript 5 introduced the Bind method, it (Bind) is unavailable in IE < 9 and Firefox 3.x. Include this Bind implementation in your code, if you are targeting older browsers:
Let’s continue with the same example we used above. The this value is also bound to another object if we assign the method (where this is defined) to a variable. This demonstrates:
When we execute the showDataVar () function, the values printed to the console are from the global data array, not the data array in the user object. This happens because showDataVar () is executed as a global function and use of this inside showDataVar () is bound to the global scope, which is the window object in browsers.
Again, we can fix this problem by specifically setting the “this” value with the bind method:
Bind () Allows us to Borrow Methods
In JavaScript, we can pass functions around, return them, borrow them, and the like. And the bind () method makes it super easy to borrow methods.
Here is an example using bind () to borrow a method:
One problem with this example is that we are adding a new method (showData) on the cars object and we might not want to do that just to borrow a method because the cars object might already have a property or method name showData. We don’t want to overwrite it accidentally. As we will see in our discussion of Apply and Call below, it is best to borrow a method using either the Apply or Call method.
JavaScript’s Bind Allows Us to Curry a Function
Function Currying, also known as partial function application, is the use of a function (that accept one or more arguments) that returns a new function with some of the arguments already set. The function that is returned has access to the stored arguments and variables of the outer function. This sounds way more complex than it actually is, so let’s code.
Let’s use the bind () method for currying. First we have a simple greet () function that accepts 3 parameters:
And we use the bind () method to curry (preset one or more of the parameters) our greet () function. The first argument of the bind () method sets the this value, as we discussed earlier:
When we use the bind () method for currying, all the parameters of the greet () function, except the last (rightmost) argument, are preset. So it is the rightmost argument that we are changing when we call the new functions that were curried from the greet () function. Again, I discuss currying at length in a separate blog post, and you will see how we can easily create very powerful functions with Currying and Compose, two Functional JavaScript concepts.
So, with the bind () method, we can explicitly set the this value for invoking methods on objects, we can borrow
and copy methods, and assign methods to variable to be executed as functions. And as outlined in the Currying Tip
earlier,
you can use bind for currying.
You should read the JavaScript 201 and the Prototype explanation before you read this.
Functions are objects in JavaScript, as you should know by now, if you have read any of the prerequisite articles. And as objects, functions have methods, including the powerful Apply, Call, and Bind methods. On the one hand, Apply and Call are nearly identical and are frequently used in JavaScript for borrowing methods and for setting the this value explicitly. We also use Apply for variable-arity functions; you will learn more about this in a bit.
On the other hand, we use Bind for setting the this value in methods and for currying functions.
We will discuss every scenario in which we use these three methods in JavaScript. While Applyand Call come with ECMAScript 3 (available on IE 6, 7, 8, and modern browsers), ECMAScript 5 (available on only modern browsers) added the Bind method. These 3 Function methods are workhorses and sometimes you absolutely need one of them. Let’s begin with the Bind method.
JavaScript’s Bind Method
We use the Bind () method primarily to call a function with the this value set explicitly. It other words, bind () allows us to easily set which specific object will be bound to this when a function or method is invoked.
This might seem relatively trivial, but often the this value in methods and functions must be set explicitly when you need a specific object bound to the function’s this value.
The need for bind usually occurs when we use the this keyword in a method and we call that method from a receiver object; in such cases, sometimes this is not bound to the object that we expect it to be bound to, resulting in errors in our applications. Don’t worry if you don’t fully comprehend the preceding sentence. It will become clear like teardrop in a moment.
JavaScript’s Bind Allows Us to Set the this Value on Methods
When the button below is clicked, the text field is populated with a random name.
JavaScript:
// <button>Get Random Person</button>
// <input type="text">
var user = {
data :[
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
clickHandler:function (event) {
var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1
// This line is adding a random person from the data array to the text field
$ ("input").val (this.data[randomNum].name + " " + this.data[randomNum].age);
}
}
// Assign an eventHandler to the button's click event
$ ("button").click (user.clickHandler);
This particular problem is quite common in JavaScript, and JavaScript frameworks like Backbone.js and libraries like jQuery automatically do the bindings for us, so that this is always bound to the object we expect it to be bound to.
To fix the problem in the preceding example, we can use the bind method thus:
Instead of this line:
JavaScript:
$ ("button").click (user.clickHandler);
JavaScript:
$ ("button").click (user.clickHandler.bind (user));
Because ECMAScript 5 introduced the Bind method, it (Bind) is unavailable in IE < 9 and Firefox 3.x. Include this Bind implementation in your code, if you are targeting older browsers:
JavaScript:
// Credit to Douglas Crockford for this bind method
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError ("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call (arguments, 1),
fToBind = this,
fNOP = function () {
},
fBound = function () {
return fToBind.apply (this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat (Array.prototype.slice.call (arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP ();
return fBound;
};
}
JavaScript:
// This data variable is a global variable
var data = [
{name:"Samantha", age:12},
{name:"Alexis", age:14}
]
var user = {
// local data variable
data :[
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
showData:function (event) {
var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1
console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
}
}
// Assign the showData method of the user object to a variable
var showDataVar = user.showData;
showDataVar (); // Samantha 12 (from the global data array, not from the local data array)
Again, we can fix this problem by specifically setting the “this” value with the bind method:
JavaScript:
// Bind the showData method to the user object
var showDataVar = user.showData.bind (user);
// Now the we get the value from the user object because the this keyword is bound to the user object
showDataVar (); // P. Mickelson 43
Bind () Allows us to Borrow Methods
In JavaScript, we can pass functions around, return them, borrow them, and the like. And the bind () method makes it super easy to borrow methods.
Here is an example using bind () to borrow a method:
JavaScript:
// Here we have a cars object that does not have a method to print its data to the console
var cars = {
data:[
{name:"Honda Accord", age:14},
{name:"Tesla Model S", age:2}
]
}
// We can borrow the showData () method from the user object we defined in the last example.
// Here we bind the user.showData method to the cars object we just created.
cars.showData = user.showData.bind (cars);
cars.showData (); // Honda Accord 14
JavaScript’s Bind Allows Us to Curry a Function
Function Currying, also known as partial function application, is the use of a function (that accept one or more arguments) that returns a new function with some of the arguments already set. The function that is returned has access to the stored arguments and variables of the outer function. This sounds way more complex than it actually is, so let’s code.
Let’s use the bind () method for currying. First we have a simple greet () function that accepts 3 parameters:
JavaScript:
function greet (gender, age, name) {
// if a male, use Mr., else use Ms.
var salutation = gender === "male" ? "Mr. " : "Ms. ";
if (age > 25) {
return "Hello, " + salutation + name + ".";
}
else {
return "Hey, " + name + ".";
}
}
JavaScript:
// So we are passing null because we are not using the "this" keyword in our greet function.
var greetAnAdultMale = greet.bind (null, "male", 45);
greetAnAdultMale ("John Hartlove"); // "Hello, Mr. John Hartlove."
var greetAYoungster = greet.bind (null, "", 16);
greetAYoungster ("Alex"); // "Hey, Alex."
greetAYoungster ("Emma Waterloo"); // "Hey, Emma Waterloo."
So, with the bind () method, we can explicitly set the this value for invoking methods on objects, we can borrow
and copy methods, and assign methods to variable to be executed as functions. And as outlined in the Currying Tip
earlier,
you can use bind for currying.