Explorer
JavaScript

The "this" Keyword

JavaScript Theory & Concepts

The "this" Keyword in JavaScript

Demystifying execution context binding, invocation rules, and lexical arrow functions.

📖 The Story & Real-World Analogy

The Microphone and the Pronoun "I"

"In human conversation, the pronoun "I" or "my" changes depending on who holds the microphone. If the CEO holds the microphone and says "I am responsible for the company", "I" means the CEO. If an intern grabs the exact same microphone and says "I am responsible for the company", "I" means the intern! In JavaScript, `this` is not determined by where the function was born, but by WHO is holding the microphone (calling the function) at runtime."

`this` is an execution context identifier that points to the object currently executing the function. Its value is evaluated at invocation time based on four precedence rules, with an exception for arrow functions.

⚙️ How It Works Under The Hood (Step-by-Step)
1

1. Default Binding (Standalone Call)

When a function is called on its own (`greet()`), `this` defaults to the global object (`window` in browsers), or `undefined` in strict mode (`"use strict"`).

2

2. Implicit Binding (Object Method)

When a function is invoked with a preceding dot (`user.greet()`), `this` is bound to the object directly to the left of the dot.

3

3. Explicit Binding (call, apply, bind)

Using `.call(obj)`, `.apply(obj)`, or `.bind(obj)` explicitly forces `this` to point to the designated object, overriding default and implicit bindings.

4

4. new Binding (Constructor Call)

When invoking with `new Person()`, JavaScript creates a brand new blank object, links its prototype, and binds `this` to that new instance.

5

Lexical this in Arrow Functions

Arrow functions do not have their own `this`. They resolve `this` lexically from their enclosing scope at the moment they are created, ignoring all 4 runtime rules.

💻 Interactive Code Walkthrough

Demonstrating implicit loss, explicit fixing, and arrow function lexical scoping:

JAVASCRIPT
const warrior = {
  name: "Thor",
  shout() {
    console.log("I am " + this.name);
  }
};

warrior.shout(); // Implicit binding: "I am Thor"

// Pitfall: Implicit Loss when extracted as a callback
const detachedShout = warrior.shout;
detachedShout(); // Default binding: "I am undefined" (in strict mode)

// Solution 1: Explicit binding via bind
const boundShout = warrior.shout.bind(warrior);
boundShout(); // "I am Thor"

// Solution 2: Arrow function retains outer lexical scope
const archer = {
  name: "Hawkeye",
  fireArrow() {
    setTimeout(() => {
      // Inherits 'this' from fireArrow() -> archer
      console.log(this.name + " hit the bullseye!");
    }, 50);
  }
};
archer.fireArrow();
Console Output:
CODE
I am Thor
I am undefined
I am Thor
Hawkeye hit the bullseye!
⚠️ Common Pitfalls & Interview Traps
Trap
Losing "this" in Callbacks and Event Listeners

The Risk: Passing `button.addEventListener("click", user.handleClick)` invokes `handleClick` with `this` bound to the button DOM element instead of `user`.

The Fix: Wrap in an arrow function `(e) => user.handleClick(e)` or pre-bind in the constructor `this.handleClick = this.handleClick.bind(this)`.

⚡ 30-Second Quick Revision Cheat Sheet (TL;DR)
  • ✓ Precedence: `new` > Explicit (`call/apply/bind`) > Implicit (`obj.fn()`) > Default.
  • ✓ In strict mode (`"use strict"`), default `this` is `undefined`, preventing global pollution.
  • ✓ Arrow functions do not bind `this`; they inherit it lexically from where they are defined.
  • ✓ Passing methods as raw callbacks causes "implicit loss" of `this`.

Finished this lesson?

Mark this chapter complete to update your learning streak and unlock the next lesson.