DEV Community

Cover image for The myth of JavaScript "this" Keyword
Shahriar Saleh Fahim
Shahriar Saleh Fahim

Posted on • Updated on

The myth of JavaScript "this" Keyword

A practical example of “this”:

Suppose you have a nice house and the house number is 15 JS Road. Your wife wants to paint the house. So she tells you “We Need to paint this house”. Notice that she is referring to the house with a this keyword. She isn’t saying we need to paint 15 JS Road House. You both are already inside that house. So she is just saying this house. The meaning of this is so simple like that. Practically there is no difference between the this in real life and the this in JavaScript.

Why the this keyword is in JS?

It helps a function to be reused in a different context.

There are 4 general rules. If you know these 4 rules you will have an idea about which object this is pointing at.

The rules are:

  1. Implicit Binding
  2. Explicit Binding
  3. New Binding
  4. Window Binding

I will now explain each rule with coding examples so that the topic will become more clearer.

1. Implicit Binding

//example-1
const fahim = {
  name: "fahim",
  age: 24,
  printUserName: function () {
    console.log(this.name); // This ""this".name" refers to the name property of the current object it is in.
  },
};

fahim.printUserName(); //fahim
Enter fullscreen mode Exit fullscreen mode

So here when we call printUserName function first we have to check if there is a “.” notation before it and if there is one then the “this” inside that function is referring to the object in which function is in. Here the function is inside the “fahim” object and it is a property of the object.

2. Explicit Binding
2.1 .Call()

////Explicit Binding(call)

const printName = function () {
  console.log(this.name); //fahim
};

const fahim = {
  name: "Fahim",
  age: 35,
};

printName.call(fahim);
Enter fullscreen mode Exit fullscreen mode

So in Implicit Binding, we saw that the this keyword refers to the object it is in. Now, what happens if we take the function out of the object and declare it globally or in another context and try to print the this.name.There is a .call() function in JS which is nothing more than calling a function explicitly. .call() receives an object as the first parameter which means the function is called within the context of the object fahim here. So we are explicitly telling the definition of this inside the function.

const printName = function (v1, v2, v3) {
  console.log(`${this.name} is ${v1},${v2} & ${v3}`); //Fahim is Hardworking,All Rounder & Best Player
};

const fahim = {
  name: "Fahim",
  age: 35,
};

const v1 = "Hardworking";
const v2 = "All Rounder";
const v3 = "Best Player";

printName.call(fahim, v1, v2, v3);
Enter fullscreen mode Exit fullscreen mode

Another use case of the .call() function is for its 2nd parameter it can take unlimited parameters. We can pass these parameters through the main function.

2.2 .Apply()

Now here we can see we have to pass a lot of parameters in the .call() function. So there is an alternative way of doing that. We can take all those parameters inside an array and pass that array inside a .apply() function. It does the same work as .call().

const printName = function (v1, v2, v3) {
  console.log(`${this.name} is ${v1},${v2} & ${v3}`); //Fahim is Hardworking,All Rounder & Best Player
};

const fahim = {
  name: "Fahim",
  age: 35,
};

const v1 = "Hardworking";
const v2 = "All Rounder";
const v3 = "Best Player";

const v = [v1, v2, v3];

printName.apply(fahim, v);
Enter fullscreen mode Exit fullscreen mode

2.3 .Bind()

.bind() also does the same work as .call(). In .call() we are directly calling the function. In .bind() it returns an instance of a function. So if store it in a variable. Then we can call the variable and it will do the job.

const printName = function (v1, v2, v3) {
  console.log(`${this.name} is ${v1},${v2} & ${v3}`); //Fahim is Hardworking,All Rounder & Best Player
};

const fahim = {
  name: "Fahim",
  age: 35,
};

const v1 = "Hardworking";
const v2 = "All Rounder";
const v3 = "Best Player";

const newName = printName.bind(fahim, v1, v2, v3);

newName();
Enter fullscreen mode Exit fullscreen mode

So there is no confusion about the definition of this in Explicit Binding as we are explicitly defining it here.

3. New Binding

function Person(name, age) {
  //let this = Object.create(null)
  this.name = name;
  this.age = age;
  console.log(`${name} is ${age} years old`);
  //return this
}

const Fahim = new Person("Fahim", 24);
const Ani = new Person("Ani", 24);
Enter fullscreen mode Exit fullscreen mode

So here Person is a constructor function. It takes two parameters name and age. We created a new Person named Fahim. So by default JS creates an object named this inside the constructor function. So, this.name points to the new Object created by JS. The name Fahim and age 24 is passed to the constructor function and this.name and this.age receives it and returns the new object.

4. Window Binding

 const PrintName = function () {
  console.log(this.name); //undefined
};

const sakib = {
  name: "Sakib",
};

PrintName();
Enter fullscreen mode Exit fullscreen mode

When all 3 rules of binding don’t work then this will just point at the window. Hence we are getting undefined. We can prove that this is equal to window if we console.log it.

const PrintName = function () {
  console.log(window===this);//true
  console.log(this.name); //undefined
};

const sakib = {
  name: "Sakib",
};

PrintName();
Enter fullscreen mode Exit fullscreen mode

To get out of this weird behavior of getting undefined we can fix it by writing “use strict”. Then JS will show us the error.

"use strict";
const PrintName = function () {
  console.log(this.name); //throws error
};

const sakib = {
  name: "Sakib",
};

PrintName();
Enter fullscreen mode Exit fullscreen mode

Note:

The first 3 rules all are applied to normal JavaScript functions but if you are using Arrow Function then simply Arrow Function is not concerned with this and even Arrow Function is introduced to decrease the confusion of using this keyword. The value of this keyword in Arrow Function is whatever context the Arrow Function is in. It can be window/global, function or object.

Discussion (0)