Tutorial

Functions in JavaScript run in a specific context, and using the this variable we have access to it.

All standard functions in the browser run under the Window context. Functions defined under an object or a class (another function) will use the context of the object it was created in. However, we can also change the context of a function at runtime, either before or while executing the function.

Binding a method to an object

To bind a function to an object and make it an object method, we can use the bind function. Here is a simple example:

var person = {
    name : "John"
};

function printName()
{
    console.log(this.name);
}

Obviously, we are not able to call printName() without associating the function with the object person. To do this we must create a bound method of the function printName to person, using the following code:

var boundPrintName = printName.bind(person);
boundPrintName();    // prints out "John"

Calling a function with a different context

We can use the call and apply functions to call a function as if it was bound to an object. The difference between the call and apply functions is only by how they receive their arguments - the call function receives the this argument first, and afterwards the arguments of the function, whereas the apply function receives the this argument first, and an array of arguments to pass on to the function as a second argument to the function.

For example, let’s call printName with person as the context using the call method:

printName.call(person);      // prints out "John"

call/apply vs bind

The difference between call/apply and bind is that bind returns a new function identical to the old function, except that the value of this in the new function is now the object it was bound to. call/apply calls the function with this being the bound object, but it does not return a return a new function or change the original, it calls it with a different value for this.

For example:

var boundPrintName = printName.call(person);    //boundPrintName gets printName's return value (null)
boundPrintName();                               //doesn't work because it's not a function, it's null

printName.bind(person);                         //returns a new function, but nothing is using it so it's useless
printName();                                    //throws error because this.name is not defined

Think of call as executing the return value of bind.

For example:

printName.call(person);     //is the same as
printName.bind(person)();   //executes the function returned by bind

Or think of bind returning a shortcut to call.

For example:

var boundPrintName = printName.bind(person); //is the same as
var boundPrintName = function()
{
    printName.call(person);
}

Exercise

Create bound copies of printFullName and printDetails to person called boundPrintFullName and boundPrintDetails.

Tutorial Code

var person = {
    firstName : "John",
    lastName : "Smith",
    age : 23
};

function printFullName()
{
    console.log(this.firstName + " " + this.lastName);
}

function printDetails()
{
    console.log(this.firstName + " is " + this.age + " years old");
}

// TODO: create bound copies of printFullName and printDetails.
var boundPrintFullName;
var boundPrintDetails;

boundPrintFullName();
boundPrintDetails();

Expected Output

John Smith
John is 23 years old