this in JavaScript
New Courses Coming Soon
Join the waiting lists
`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)
)
Here is how can I help you:
- COURSES where I teach everything I know
- CODING BOOTCAMP cohort course - next edition in 2025
- THE VALLEY OF CODE your web development manual
- BOOKS 17 coding ebooks you can download for free on JS Python C PHP and lots more
- Interesting links collection
- Follow me on X