Skip to main content

Command Palette

Search for a command to run...

Understanding this Keyword in JavaScript

Published
6 min read
Understanding this Keyword in JavaScript

If you've spent any time with JavaScript, you've probably run into this and thought : "okay what is this thing and why does it keep breaking my code?"

You're not alone. this is one of those concepts that feels confusing at first, but once it clicks, you'll wonder why it ever confused you. Let's fix that today.

In simple words : The keyword this refers to the object that is currently calling the function.

“this = who is calling the function”

Once you understand this idea, most of the confusion disappears.

1. What Does this Represent?

The value of this depends on how a function is called, not where it is written.

this is the object that called the function. That's it. Not where the function was defined, not what the function does, purely who ran it. Every confusing behavior of this traces back to this single idea.

Basic Example :

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

show(); // global object

Think of it like the word "home." If you ask Ravi where home is, he'll say Mumbai. Ask Priya the same question and she'll say Delhi. The word "home" is the same, but what it points to depends entirely on who's asking. this works the same way : it's a pointer whose value depends on the context of the call.

2. this in the Global Context

When you write code at the top level : outside any function or object, this points to the global object. In a browser, that's window. In Node.js, it's global.

console.log(this);             // Window { ... } in a browser
console.log(this === window);  // true

You can think of the global context as JavaScript's default home. When no specific object is making the call, this falls back here automatically.

One thing worth knowing early: in strict mode ('use strict'), this inside a regular function becomes undefined instead of pointing to the global object. This is a deliberate safety feature to stop you from accidentally creating or modifying global variables when you didn't intend to. You'll encounter strict mode often in modern JavaScript, so it's good to keep this in the back of your mind.

3. this Inside Objects

This is where this stops being abstract and starts being genuinely useful. When a function is a method on an object and you call it through that object, this points to the object itself.

const person = {
  name: 'Arjun',
  greet: function() {
    // `this` is `person`, because person is the one calling greet()
    console.log('Hello, I am ' + this.name);
  }
};

person.greet(); // Hello, I am Arjun

Here's a practical trick to always get this right: look at what's to the left of the dot at the call site. Whatever object you see there is what this will be inside the function. person.greet(), person is to the left, so this is person.

4. this Inside Functions

Here's where most people hit their first real wall with this, so let's walk through it carefully.

If you take a method off an object and call it as a plain, standalone function, it loses its context. There's no longer an object to the left of the dot, so this reverts to the global object (or undefined in strict mode).

js

const person = {
  name: 'Priya',
  greet: function() {
    console.log('Hello, I am ' + this.name);
  }
};

const sayHello = person.greet;  // detached — just a reference to the function

sayHello();  // Hello, I am undefined  ← `this` is now window, not person

When you assigned person.greet to sayHello, you only copied the function reference, you didn't carry the object along with it. So when sayHello() runs, JavaScript looks for a caller to the left of the dot, finds nothing, and defaults to global. Since window.name doesn't exist in your code, you get undefined.

this inside Arrow Functions :

Arrow functions are the clean solution to this. Unlike regular functions, an arrow function doesn't have its own this at all — it simply inherits this from wherever it was written (its surrounding scope). This means it locks in the value of this at definition time, not call time.

const user = {
  name: 'Kiran',
  sayHi: function() {
    // Arrow function inherits `this` from sayHi(), where `this` is `user`
    setTimeout(() => {
      console.log('Hi, ' + this.name);  // Hi, Kiran ✓
    }, 500);
  }
};

user.sayHi();

The arrow function inside setTimeout looks outward to sayHi()'s scope to find this, and since sayHi was called as user.sayHi(), this there is user. Problem solved.

5. How the Calling Context Changes this

JavaScript gives you three built-in methods : call(), apply(), and bind() , to take manual control of this. Think of them as tools for saying "run this function, but pretend this specific object called it."

call() invokes the function immediately with a this you choose:

function introduce() {
  console.log('Hi, I am ' + this.name);
}

const user1 = { name: 'Ravi' };
const user2 = { name: 'Meera' };

introduce.call(user1);  // Hi, I am Ravi
introduce.call(user2);  // Hi, I am Meera

apply() does exactly the same thing, but you pass any extra arguments as an array rather than individually. Functionally, call and apply are nearly identical, the only difference is that syntax detail.

bind() is different in one important way: instead of calling the function immediately, it returns a new function that is permanently locked to the this you specify, no matter how or where it gets called later.

function introduce() {
  console.log('Hi, I am ' + this.name);
}

const greetAsRavi = introduce.bind({ name: 'Ravi' });

greetAsRavi();          // Hi, I am Ravi — always, no matter what
greetAsRavi.call({ name: 'Someone Else' });  // Still: Hi, I am Ravi

bind() is especially valuable when you're passing a method as a callback, situations where you know the function will lose its context. Instead of relying on arrow functions or workarounds, you can just bind it upfront and trust it'll always have the right this.

Conclusion

At its core, this comes down to one question you should ask every time you see it: who is calling this function right now? Follow the dot at the call site, trace the caller, and this almost always makes perfect sense. Global code defaults to the global object, object methods point back to the object, detached functions lose their context, and arrow functions simply inherit this from wherever they were written. When you need full control, call, apply, and bind let you set the caller yourself.

What makes this feel tricky at first is that the same function can behave differently depending on how it's invoked, not how it's written. That flexibility is actually what makes this so powerful, one reusable function can work correctly across many different objects just by calling it the right way.

1 views