What exactly is 'this'? Understanding JavaScript's Call(), Bind(), and Apply() methods.
Understanding this concept in relation to call, bind and apply.
Table of contents
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 🙂