Deep Dive: Mastering the JavaScript this Keyword

Hey there! If you’ve ever tried logging this in JavaScript and got undefined or something totally unexpected, you’re not alone. The this keyword is one of the trickiest parts of JS—but once you get it, it makes your code way cleaner and easier to debug.

In this guide, we’ll break down this in simple terms and show how it works in:

  • Global context
  • Strict vs non-strict mode
  • Normal functions
  • Object methods
  • Arrow functions
  • Classes and constructors
  • Explicit binding with call, apply, and bind

What is this in JavaScript?

Simply put: this is the object that’s currently running the function.

The main rule to remember: it depends on how the function is called, not where it’s written.

this in the Global Context

When you use this in the global scope:

console.log(this);
  • In a browser → it points to window
  • In Node.js → it points to global

Pretty straightforward, right? This is just the default behavior.

Normal Functions: Strict vs Non-Strict Mode

Non-Strict Mode

By default, when a normal function runs without an object, this is automatically the global object:

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

show(); // window (browser)

Strict Mode ('use strict')

With strict mode, JS doesn’t auto-bind this—so you get:

'use strict';

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

show(); // undefined

Strict mode helps avoid accidentally messing with the global object.

Note: JS classes always run in strict mode.

this Inside Object Methods

When a function is called as an object method, this points to the object before the dot:

const user = {
  name: "BigTechie",
  greet() {
    console.log(this.name);
  }
};

user.greet(); // BigTechie

So here, this is user because we did user.greet().

Arrow Functions and this

Arrow functions are a bit different. They don’t have their own this. Instead, they use this from the surrounding code (lexical scope).

const user = {
  name: "BigTechie",
  greet: () => {
    console.log(this.name);
  }
};

user.greet(); // undefined

Here, this is taken from the outer scope (global), not the object.

Tip: Use arrow functions when you want to keep this from the parent, like inside callbacks.

Constructors and Classes

Constructor Functions

function Person(name) {
  this.name = name;
}

const dev = new Person("Dev");
console.log(dev.name); // Dev

Classes

class Student {
  constructor(name) {
    this.name = name;
  }

  sayHi() {
    console.log(this.name);
  }
}

const s1 = new Student("BigTechie");
s1.sayHi(); // BigTechie

Inside classes, this always refers to the current instance.

Explicit Binding: call, apply, and bind

function greet(city) {
  console.log(`${this.name} from ${city}`);
}

const user = { name: "BigTechie" };

greet.call(user, "Hyderabad");
greet.apply(user, ["Hyderabad"]);

const boundGreet = greet.bind(user);
boundGreet("Hyderabad");
  • call() – arguments individually
  • apply() – arguments as an array
  • bind() – returns a new function with fixed this

Common Pitfall: this in Callbacks

const user = {
  name: "Dev",
  showName() {
    console.log(this.name);
  }
};

setTimeout(user.showName, 1000); // undefined

When passing methods as callbacks, this can get lost.

Fix it: use bind():

setTimeout(user.showName.bind(user), 1000); // Dev

Quick Summary

Scenario Value of this
Global scope (browser) window
Normal function (non-strict) Global object
Normal function (strict) undefined
Object method Object before the dot
Arrow function Lexical scope
Constructor / Class Current instance

Final Thoughts

Confused about this? Ask yourself: “How is this function being called?” If you can answer that, you already know what this refers to.

Comments

Popular posts from this blog