Skip to content

this in JavaScript

New Course Coming Soon:

Get Really Good at Git

`this` is a value that has different values depending on where it's used. Not knowing this tiny detail of JavaScript can cause a lot of headaches, so it's worth taking 5 minutes to learn all the tricks

this is a keyword that has different values depending on where it’s used.

Not knowing this tiny detail of JavaScript can cause a lot of headaches, so it’s worth taking 5 minutes to learn all the tricks.

this in strict mode

Outside any object, this in strict mode is always undefined.

Notice I mentioned strict mode. If strict mode is disabled (the default state if you don’t explicitly add 'use strict' on top of your file ), you are in the so-called sloppy mode, and this - unless some specific cases mentioned here below - has the value of the global object.

Which means window in a browser context.

this in methods

A method is a function attached to an object.

You can see it in various forms.

Here’s one:

const car = {
  maker: 'Ford',
  model: 'Fiesta',

  drive() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}

car.drive()
//Driving a Ford Fiesta car!

In this case, using a regular function, this is automatically bound to the object.

Note: the above method declaration is the same as drive: function() {…, but shorter:

const car = {
  maker: 'Ford',
  model: 'Fiesta',

  drive: function() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}

The same works in this example:

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}

car.drive = function() {
  console.log(`Driving a ${this.maker} ${this.model} car!`)
}

car.drive()
//Driving a Ford Fiesta car!

An arrow function does not work in the same way, as it’s lexically bound:

const car = {
  maker: 'Ford',
  model: 'Fiesta',

  drive: () => {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}

car.drive()
//Driving a undefined undefined car!

Binding arrow functions

You cannot bind a value to an arrow function, like you do with normal functions.

It’s not possible due to the way they work. this is lexically bound, which means its value is derived from the context where they are defined.

Explicitly pass an object to be used as this

JavaScript offers a few ways to map this to any object you want.

Using bind(), at the function declaration step:

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}

const drive = function() {
  console.log(`Driving a ${this.maker} ${this.model} car!`)
}.bind(car)

drive()
//Driving a Ford Fiesta car!

You could also bind an existing object method to remap its this value:

const car = {
  maker: 'Ford',
  model: 'Fiesta',

  drive() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}

const anotherCar = {
  maker: 'Audi',
  model: 'A4'
}

car.drive.bind(anotherCar)()
//Driving a Audi A4 car!

Using call() or apply(), at the function invocation step:

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}

const drive = function(kmh) {
  console.log(`Driving a ${this.maker} ${this.model} car at ${kmh} km/h!`)
}

drive.call(car, 100)
//Driving a Ford Fiesta car at 100 km/h!

drive.apply(car, [100])
//Driving a Ford Fiesta car at 100 km/h!

The first parameter you pass to call() or apply() is always bound to this. The difference between call() and apply() is just that the second one wants an array as the arguments list, while the first accepts a variable number of parameters, which passes as function arguments.

The special case of browser event handlers

In event handlers callbacks, this refers to the HTML element that received the event:

document.querySelector('#button').addEventListener('click', function(e) {
  console.log(this) //HTMLElement
}

You can bind it using

document.querySelector('#button').addEventListener(
  'click',
  function(e) {
    console.log(this) //Window if global, or your context
  }.bind(this)
)
Are you intimidated by Git? Can’t figure out merge vs rebase? Are you afraid of screwing up something any time you have to do something in Git? Do you rely on ChatGPT or random people’s answer on StackOverflow to fix your problems? Your coworkers are tired of explaining Git to you all the time? Git is something we all need to use, but few of us really master it. I created this course to improve your Git (and GitHub) knowledge at a radical level. A course that helps you feel less frustrated with Git. Launching May 21, 2024. Join the waiting list!
→ Get my JavaScript Beginner's Handbook
→ Read my JavaScript Tutorials on The Valley of Code
→ Read my TypeScript Tutorial on The Valley of Code

Here is how can I help you: