DEV Community

Cover image for `this` in JavaScript Explained
Sanjeev Sharma
Sanjeev Sharma

Posted on • Originally published at frontendcamp.in

`this` in JavaScript Explained

This is question #5 of Frontend Interview Questions series. If you're looking to level up your preparation or stay updated in general, consider signing up on Frontend Camp.


The this keyword always refers to the current context of a function or script.

this is a confusing topic for most of us (pun intended), but it doesn't have to be. All you need to do is remember some rules.

Following rules, in order of precedence, dictate how value of this is determined during runtime:

Usage in a Function constructor

If a function is called with the new keyword, this inside the function refers to the newly created object instance.

function Book(title) {
  console.log(this);
  this.title = title;
  console.log(this);
}

const book1 = new Book('Jungle Book');

// {}
// { title: "'Jungle Book' }"

console.log(book1.name); // 'Jungle Book'
Enter fullscreen mode Exit fullscreen mode

Explicitly binding this

call(), apply() or bind() can be used to explicitly set the value of this inside a function.

  • call() and apply() are used when a function needs to be invoked immediately.
  • bind() returns a new function to be used later.
const obj = { name: 'Ben' };

function sayHello() {
  console.log(`Hello, ${this.name}!`);
}

const sayHelloToBen = sayHello.bind(obj);

sayHelloToBen(); // Hello, Ben!
sayHello.call(obj); // Hello, Ben!
sayHello.apply(obj); // Hello, Ben!
Enter fullscreen mode Exit fullscreen mode

Usage in a method call

If a function is a method of an object, then this refers to the object.

const person = {
  name: 'Ben',
  logThis: function() {
    console.log(this);
  }
}

person.logThis(); // { name: 'Ben', logThis: fn() }
Enter fullscreen mode Exit fullscreen mode

Usage in a Regular function call (Free function invocation)

If a function is invoked in the global context, then this refers to the global object(in non-strict mode) or undefined(in strict mode).

For browsers, the global object is window.

// Browser

function showThis() {
  console.log(this);
}

showThis(); // Window { open: fn, alert: fn, ... }
Enter fullscreen mode Exit fullscreen mode

When a function is declared in the global context, it becomes a property of the window object. Calling window.showThis() would yield the same result. This is why it's an implicit method invocation. (Refer the rule above this one)

If multiple rules apply, then the rule with higher precedence will apply.

const obj1 = {
    value: 1,
    showThis: function() {
        console.log(this);
    },
};

const obj2 = { value: 2 };

obj1.showThis.call(obj2); // { value: 2 }
Enter fullscreen mode Exit fullscreen mode

In the example above, two rules are being applied: Method invocation and Explicit binding. As explicit binding has higher precedence, it gets to set the value of this.

Arrow functions

Arrow functions don't follow the rules stated above as they don't have a this value of their own. They pick the this value from the parent scope.

const person = {
  name: 'Ben',
  showThis: () => {
    console.log(this);
  },
  showThisWrapped: function() {
    const arrowFn = () => console.log(this);
    arrowFn();
  }
}

person.showThis(); // Window { open: fn, alert: fn, ... }
person.showThisWrapped(); // { name: 'Ben', showThis: fn, showThisWrapped: fn }
Enter fullscreen mode Exit fullscreen mode

This is why you should avoid using arrow functions for event listeners. Event listeners bind the HTML element to the this value but if the handler is an arrow function, it is not possible.

document.querySelector('#cta').addEventListener('click', function(){
 console.log(this); // HTMLButtonElement
})

document.querySelector('#cancel').addEventListener('click', () => {
 console.log(this); // Window
})
Enter fullscreen mode Exit fullscreen mode

Summary

  1. In a function constructor(new Person()), this will be the newly created object instance.
  2. If explicitly bound using bind(), call() or apply(), this inside the function will be set to the value provided.
  3. Inside a method, this is set to the object that method is a property of.
  4. Inside a free function invocation, this points to global object(non-strict mode) or undefined(strict mode).
  5. If multiple rules apply, the rule stated first(1-4) will apply.
  6. Arrow functions don't have their own this. Its value is picked from the parent scope.

Like what you just read? Consider joining the waitlist on Frontend Camp ✌️

Top comments (2)

Collapse
 
tdjdev profile image
Davy TISSOT

You made a small error. You have writted console.log(book1.name); instead of console.log(book1.title);

Collapse
 
thesanjeevsharma profile image
Sanjeev Sharma

Good spot!