Learn this Keyword in JavaScript the Easy Way
What is the infamous this in JavaScript, implicit and explicit binding? Learn about it in this post.

π¨ Be cautious - Donβt compare this keyword of JavaScript with other programming languages. The working of JavaScript is inherently different from that of object-oriented programming languages like C++, Java, OR π Python.
Letβs start with the anatomy of this.

Anatomy of this
A functionβs this keyword refers to the execution context for that function call. Note that, the function call and not the function was defined. π¨ It doesnβt matter how the function was defined, what will be this keyword entirely depends on how the function was called.
Therefore, a this aware function can have a different context each time itβs called. This is amazing. It makes this keyword very flexible and reusable. Itβs somewhat JavaScriptβs version of dynamic scope. Read more about the difference between lexical scope and dynamic scope in the Lexical Scope section of Get an in-depth view of Scopes in JavaScript article.
Consider the following code:
function eat(person) {
console.log(`${person} is eating ${this.food}`);
}
function restaurant() {
var foodContext = {
food: "πππ",
};
eat.call(foodContext, "John");
}
restaurant(); // John is eating πππ
Here, eat is a this aware function. In the restaurant function, we use the call method on eat function for binding the this keyword of eat with a context which in this case is foodContext. This is called hard binding (more on this later in the post).
Since during the call, eat functionβs this refers to the foodContext, we have this.food as πππ. This is mind-blowing because now you can use the eat function with multiple contexts. π₯ this provides flexibility that lexical scopes donβt provide.
function eat(person) {
console.log(`${person} is eating ${this.food}`);
}
function restaurant() {
var breakfast = { food: "πππ" };
eat.call(breakfast, "Breakfast");
var lunch = { food: "π₯π₯π₯" };
eat.call(lunch, "Lunch");
var dinner = { food: "π₯π₯π₯" };
eat.call(dinner, "Dinner");
}
restaurant();
// Output:
// Breakfast is eating πππ
// Lunch is eating π₯π₯π₯
// Dinner is eating π₯π₯π₯
What is hard binding? Well, there are 4 different ways of invoking a function and each one of them will give a different this context.

Implicit Binding
What happens when you donβt explicitly bind this keyword to a context?
// Namespace pattern
var restaurant = {
food: "πππ",
eat(person) {
console.log(`${person} is eating at ${this.food}`);
},
};
restaurant.eat("π΅"); // π΅ is eating at πππ
Here, this.food is πππ not because the eat function is inside the restaurant object, so this points to the restaurant. Itβs because, in the call site, eat is invoked with the restaurant object.
The detail that this keyword depends on how the function is called (manner of the function call) and not how itβs defined is very important because if we were to use a callback in this scenario then the call site would be different and hence this keyword would be pointing on a different object.
// Namespace pattern
var restaurant = {
food: "πππ",
eat(person) {
console.log(`${person} is eating at ${this.food}`);
},
};
function personEating(person, callback) {
callback(person);
}
personEating("π΅", restaurant.eat);
Here, this keyword is pointing to the personEating context. So if we had [this.food](http://this.food) inside the personEating function then this.food wonβt be undefined. For example:
function anotherPersonEating(person, callback) {
this.food = "πππ";
callback(person);
}
anotherPersonEating("π΅", restaurant.eat); // π΅ is eating at πππ
This raises another issue while using callbacks, we lose our this. This issue is solved by hard binding. Having implicit binding helps to share methods (behavior) among different contexts. Itβs an intentional tradeoff between predictable and flexible. To share behaviors letβs learn about explicit binding.

Explicit Binding
We can use call OR apply methods on a function to explicitly tell JavaScript, which context to invoke the function in.
function eat(person) {
console.log(`${person} is eating ${this.food} in ${this.name}`);
}
var mcDonalds = {
name: "McDonalds",
food: "πππ",
};
var pizzaHut = {
name: "Pizza Hut",
food: "πππ§",
};
// Using .call
eat.call(mcDonalds, "John");
// John is eating πππ in McDonalds
// Using .apply
eat.apply(pizzaHut, ["John"]);
// John is eating πππ§ in Pizza Hut
A variation of explicit binding is hard binding. Here we solve the issue of losing this binding. This issue commonly happens when working with callbacks. Read more on this in the Implicit Binding section.
var pizzaHut = {
name: "Pizza Hut",
food: "πππ§",
eat(person) {
console.log(`${person} is eating ${this.food}`);
},
};
setTimeout(pizzaHut.eat, 1000, "π΅"); // π΅ is eating undefined
What happens is that the call site is different, it is inside the setTimeout, and depending on its call site our this behaves because of which we get undefined (since this.food wonβt be defined there). To solve this issue we use the bind method on a function which will produce a new function that will be bound to the context we provide. π¨ This will take away the flexibility offered by this keyword.
Also, note that apply and call will also give the same results but instead of returning a new function, they will just execute the function in hand. π On a side note, the setTimeout utility is defined by HTML, itβs not invoking it just with the default call, it actually explicitly invokes it with a .call in the context of global. So the this points to the global object for the setTimeout.
π¨ Note on the flexibility provided by this keyword
If we were to go to all the trouble to define a bunch of functions on some namespace object and have this in front of every property reference and every method access, AND then if all of your function calls use the bind, then we would be cutting yourself off at the knees β.
This is because you put all the this keywords for its dynamic feature and then use bind to remove that dynamic feature. A better thing to do in this case will be to write a module that uses closure and has a fixed, predictable behavior.
Conclusion
this keyword provides flexibility that lexical scope and closures donβt. We can opt-out of this flexibility by hard binding but be cautious to not overdo it because it dilutes the purpose of using this.
This is the end of this post but not for this keyword top. There are some topics such as the new keyword, default binding, binding precedence, and this inside an arrow function. So to not miss anything do π₯ follow me and if you like the post then donβt forget to give it a ππΌ.




