What exactly is 'this'? Understanding JavaScript's Call(), Bind(), and Apply() methods.

Understanding this concept in relation to call, bind and apply.

What exactly is 'this'? Understanding JavaScript's Call(), Bind(), and Apply() methods.

A commonly used keyword in some programming languages is this. This term allows you to refer to an object from within it. One of the more perplexing aspects of Javascript is that this value varies based on the context in which it is invoked.

It refers to the global scope by default, but it refers to the function when invoked within it. We'll learn about the this keyword, as well as why and when to utilize call, bind, and apply in JavaScript, in this article.

The value of this is assigned when a method or function is called. And NOT where it is defined!

const myLanguages = {
  firstLanguage:"Javascript",
  secondLanguage: "Python",
  language() {
    return `I code in ${this.firstLanguage} and ${this.secondLanguage}`;
  }
}

In the example above, the method language() has access to the properties of its object myLanguages, and therefore the this is function-scoped in this situation. In this scenario, myLanguages.language() would return as shown below.

myLanguages.language(); //I code in Javascript and Python

In another scenario, let us assign the method to the variable globalScope. If we try to console this variable, we can see that the this is no longer accessible within the myLanguages object; instead, it is now global scoped and it is now pointing to the window object and it would return an undefined because firstLanguage and secondLangauge are not available globally.

const globalScope = myLanguages.language
console.log(globalScope()) //I code in undefined and undefined

However, if we set a firstLanguage and secondLangauge property to the window object, we can now access both properties globally using the method of the myLanguages object.

window.firstLanguage = "Laravel";
window.secondLanguage = "Golang";
console.log(globalScope()) //I code in Laravel and Golang

So again, to reiterate, the value of this is assigned only when a method or function is called, not when it is defined. Although the this keyword was specified within the scope of the function, its value was allocated at the point where it was invoked in our example.

Now that we have a fundamental knowledge of how the this concept works, we can now delve into the call, bind, and apply methods as these concepts would help solve the issue of this scope.

Using these predefined methods, we can assign the value of this to whatever we want as they can be used to set the this keyword independent of how a function is called.

Call()

This is a method that is predefined in JavaScript. It's used to call or invoke a method that takes the owner object as an argument. An object can use a method that belongs to another object by using the call() function. You can write a method once and then call it from another object without having to rewrite the method.

The format for a call() method can be seen as:

Object.function.call(this.Args)

In the example below, we have two objects relation1 and relation2 that can access the method faveRelation and we utilize the call() method with the owner object as its argument to scope this to be particular for each object.

const person = {
 faveRelation() {
 return `${this.name} is my favourite ${this.relation}`;
 }
}
const relation1 = {
 name:"Jamie",
 relation: "uncle"
}
const relation2 = {
 name:"Austin",
 relation: "nephew"
}
person.faveRelation.call(relation1); //Jamie is my favourite uncle
person.faveRelation.call(relation2); //Austin is my favourite nephew

The call() method accepts arguments as well. These arguments are comma-separated. They will be passed to the function call.

The format for a call() method with arguments can be seen as :

Object.function.call(this.Args, argument1, argument2, ...)

The code below is similar to what we had before, except it now includes method arguments.

const person = {
 faveRelation(city, country) {
 return `${this.name} is my favourite ${this.relation} and he lives in ${city},${country}`;
 }
}
const relation1 = {
 name:"Jamie",
 relation: "uncle"
}
const relation2 = {
 name:"Austin",
 relation: "nephew"
}
person.faveRelation.call(relation1, "Lagos", "Nigeria"); //Jamie is my favourite uncle and he lives in Lagos,Nigeria
person.faveRelation.call(relation2, "Benin-city", "Nigeria"); //Austin is my favourite nephew and he lives in Benin-city,Nigeria

Apply() Method

The apply() method is similar to the call() method. The distinction is that the call() method takes individual parameters, whereas the apply() method takes an array of arguments. A TypeError will occur if this is not done.

The format for an apply() method with arguments can be seen as :

Object.function.call(this.Args, [argument1, argument2, ...])

The apply() method is very handy if you want to use an array instead of an argument list.

If you had an array of numbers, say [1, 2, 3], and you want to determine the largest number, you could use this method. You'd utilize the apply() method with the array of integers as an argument, using the Math object and the max method. Because we don't have an object to refer to, the null keyword is used.

The null value is used in JavaScript to represent the intentional absence of any object value.

console.log(Math.max.apply(null,1,2,3)) // TypeError
console.log(Math.max.apply(null,[1,2,3])) // 3

Using the example below, let us see how the apply() method is used.

const person = {
 faveRelation: function(city, country) {
 return `${this.name} is my favourite ${this.relation} and he lives in ${city},${country}`;
 }
}
const relation1 = {
 name:"Jamie",
 relation: "uncle"
}
const relation2 = {
 name:"Austin",
 relation: "nephew"
}
person.faveRelation.apply(relation1, ["Lagos", "Nigeria"]); //Jamie is my favourite uncle and he lives in Lagos,Nigeria
person.faveRelation.apply(relation2, ["Benin-city", "Nigeria"]); //Austin is my favourite nephew and he lives in Benin-city,Nigeria

Bind() method

The bind() method, unlike the call() and apply() methods, does not instantly execute the function. It simply returns a new version of the function whose this sets to argument thisArg .

The format for a bind() method can be seen as :

const bound = Object.function.bind(thisArgs);
bound()

In the example below, we called the bind() method of the person.faveRelation() method and pass in the relation1 as its argument. The boundFavePerson() function is then called.

const person = {
 faveRelation: function() {
 return `${this.name} is my favourite ${this.relation}`;
 },
 favAnimal: function(hobby, animal) {
 return `${this.name} enjoys ${hobby} and loves ${animal}`;
 }
}
const relation1 = {
 name:"Jamie",
 relation: "uncle"
}
const relation2 = {
 name:"Austin",
 relation: "nephew"
}
const boundFavePerson = person.faveRelation.bind(relation1); 
console.log(boundFavePerson()); //Jamie is my favourite uncle

You can call the bind() method by passing the arguments directly or passing the arguments in the bound function itself.

You can either pass the arguments directly to the bind() method (Method1) or pass the arguments to the bound function itself (Method2).

The format for a bind() method with arguments can be seen as :

//Method1
const bound = Object.function.bind(thisArgs, argument1, argument2);
bound()

//Method2
const bound = Object.function.bind(thisArgs);
bound(argument1, argument2)
//Arguments passed directly
const boundPerson = person.favAnimal.bind(relation1, "surfing", "dogs"); 
console.log(boundPerson()); //Jamie enjoys surfing and loves dogs.

//Arguments passed in the bound function itself
const boundPerson1 = person.favAnimal.bind(relation2); 
console.log(boundPerson1("reading", "cats")); //Austin enjoys reading and loves cats

Conclusion

From this article, we have learned:

  • How the this keyword is scoped in Javascript.

  • When a method or function is invoked, the value of this is assigned, not when it is defined.

  • We also learned how to set the this keyword regardless of how a function is invoked using the call, bind, and apply methods.

If you found this article useful, please share it with your network, and if you have any comments, please drop them! I'd be delighted to help 🙂

References