JavaScript .call() .apply() and .bind() — explained to a total noob

JavaScript has a number of built in function/methods that can apply to various data types.

Just as .split(“”) can apply to a string, .call(), .apply() and .bind() are methods of functions.

These 3 functions are all designed to set CONTEXT, or more specifically, what “this” refers to.

Most of the time, you would always define “this” or have it specifically included in a function. For instance, lets say you have an object:

var owen = {
 name: "Owen"
}

And you want to reference this object using a function:

function sayTo(person, first, second){
 return first + " " + person.name + " " + second;
}
sayTo(owen, "Hi", "how are you?");
//returns "Hi Owen how are you?"

Now, if invoked the sayTo function on Owen, with 2 arguments, it would invoke correctly, because

Now, what if sayTo was defined a little differently?

var owen = {
name: "Owen"
}
function sayTo(first, second){
console.log(this);
return first + " " + this.name + " " + second;
}
sayTo(owen, "Hi", "how are you?");
//returns "[Object] undefined Hi"

The first argument, owen, goes to the first variable, “hi” goes to the second variable, and “how are you?” goes nowhere, and this.name is undefined, because this is NOT the object owen.

The this when you console.log it, actually returns the global window object.

Using .call()

.call() allows the sayTo function to work:

var owen = {
name: "Owen"
}
function sayTo(first, second){
console.log(this);
return first + " " + this.name + " " + second;
}
sayTo.call(owen, "Hi", "how are you?");
//this is now the owen object
//returns "Hi Owen how are you?"

The notation is as follows:

functionName.call(value of this, arg1, arg2…)

.call essentially forces the value in this in whichever function .call is applied on. In this case, we invoke the sayTo function. .call(owen, …) forces the this of sayTo() to be the owen object. Thus this.name is applicable.

“Hi” and “how are you?” are entered in as the second or third argument of the sayTo function (which takes 2 arguments).

Using .apply()

Using .apply() is very similar to .call. The only difference is that .call() takes arg1 and arg2 just one after another.

For .apply() to work, arguments 1 and 2 need to be entered as an array:

var owen = {
name: "Owen"
}
function sayTo(first, second){
console.log(this);
return first + " " + this.name + " " + second;
}
sayTo.apply(owen, ["Hi", "how are you?"]);
//this is now the owen object
//returns "Hi Owen how are you?"

The format is as follows:

functionName.apply(value of this, [arg1, arg2 …])

Notice that arg1 and arg2 are entered as an array.

Using .bind()

.bind(), unlike .apply() and .call(), returns a function instead of a value.

.bind() sets the value of this and changes the function to a new function, but it doesn’t invoke the function.

var owen = {
name: “Owen”
}
function sayTo(first, second){
return first + “ “ + this.name + “ “ + second;
}
var sayToOwen = sayTo.bind(owen);

Essentially, sayToOwen is create as a new function. Which is techincally:

var sayToOwen = function(first, second){
 return first + “ “ + owen.name + “ “ + second;
}

You can then run sayToOwen as a normal function.

You can also “bind” the arguments of sayTo() as well:

var owen = {
name: “Owen”
}
function sayTo(first, second){
return first + “ “ + this.name + “ “ + second;
}
var sayHiToOwen = sayTo.bind(owen, "Hi");

The variable sayHiToOwen then becomes:

var SayHiToOwen = function(second){
return "Hi" + " " + owen.name + " " + second;
}

Summary

.call()
Function.call(value of this, arg1, arg2, …)
//Will execute Function

.apply()
Function.apply(value of this, [arg1, arg2, ..])
//Will execute Function

.bind()
newFunction = Function.bind(value of this, arg1, arg2 …) 
//Will return a new function