Skip to main content

Command Palette

Search for a command to run...

Understanding the this Keyword in JavaScript

Updated
4 min readView as Markdown
Understanding the this Keyword in JavaScript

If there is one feature in JavaScript that has caused more sleepless nights and frantic console logs than any other, it is the this keyword.

In most programming languages, this behaves predictably: it always refers to the class or object it was written inside. But JavaScript is different. In JavaScript, this is a shape-shifter. Its value doesn't depend on where you wrote the function; it depends entirely on how the function is called.

Think of this like a pronoun in English. If I say, "He dropped the ball," the word "he" means nothing on its own. It only makes sense if you know who we are currently talking about.

Let's look at the simple rules to figure out exactly "who" this is talking about at any given moment.

The Golden Rule: Look to the Left of the Dot

If you memorize only one thing about the this keyword, make it this: Whenever a function is executed, look immediately to the left of the dot that called it. That object is this.

Let's see this in action inside a standard object:

const player = {
  username: "Alex",
  score: 100,
  announce() {
    // Who is 'this'? Let's find out!
    console.log(`Player \({this.username} has \){this.score} points.`);
  }
};

// Look to the left of the dot! The caller is 'player'
player.announce(); 
// Output: Player Alex has 100 points.

When we execute player.announce(), the JavaScript engine looks at the call, sees player sitting to the left of the dot, and says, "Ah! The player object is the one calling the function. Therefore, this = player."

It really is that simple. But what happens when there is no dot?

The Wildcard: Calling Regular Functions

What if we write a normal, standalone function that isn't attached to an object, and we use this inside of it?

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

// There is no dot here! Who is the caller?
sayHello(); 

Because there is no object to the left of a dot, JavaScript defaults to the highest possible level.

  • In a browser, this will default to the massive global window object.

  • If you are using Strict Mode ("use strict";), JavaScript refuses to default to the window object to protect you from accidentally changing global variables. Instead, this will simply be undefined.

The Trap: Losing Your Context

The absolute most common bug developers face with this happens when a function is detached from its object before it is called.

Let's look at a classic mistake. We take the exact same announce method from our player object, but we assign it to a new variable before running it:

const player = {
  username: "Alex",
  announce() {
    console.log(`Hello, I am ${this.username}`);
  }
};

// We assign the function to a variable, but we don't call it yet
const detachedFunction = player.announce;

// Now we call it. Look to the left of the dot... wait, there is no dot!
detachedFunction(); 
// Output: Hello, I am undefined

What happened? Remember, this does not care where the function was created. It only cares how it is executed. When we executed detachedFunction(), there was no player. attached to it. It was called as a plain global function. Therefore, this became the global object (or undefined), and it couldn't find a username property.

We lost our context! This happens all the time when passing object methods as callbacks into things like setTimeout or React event listeners.

The Global Context: Naked this

Finally, what if you just type this right out in the open, not inside any function or object at all?

console.log(this);

If you do this in the global scope (the top level of your file), this simply refers to the global execution context. In a web browser, this will log the window object. In Node.js, it will log an empty global module object.

The this keyword isn't magic, and it isn't broken—it is just highly dependent on context.

To master it, stop looking at where the function was written, and start looking at the exact line of code where the function is executed. If there is an object to the left of the dot, that object is this. If there isn't, you are in the global scope