DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
  1. Home
  2. Articles
  3. Frontend Engineering
  4. The "this" Keyword in JavaScript — The Complete Mental Model
XLinkedInReddit
MediumFrontend Engineering

The "this" Keyword in JavaScript — The Complete Mental Model

D
DevPrep Team
February 9, 2026·4 min read·0
Table of Contents
  • The 5 Rules of "this" — In Order of Priority
  • Rule 1: new Binding (Highest Priority)
  • Rule 2: Explicit Binding — call, apply, bind
  • Rule 3: Implicit Binding — Object Method
  • Rule 4: Default Binding — Standalone Function
  • Rule 5: Arrow Functions — Lexical "this"
  • The Classic Pitfall — Losing "this" in Callbacks
  • Real Production Issues
  • Issue 1: Event Handler "this" in Vanilla JS
  • Issue 2: setTimeout Losing Context
  • Issue 3: Destructured Methods
  • Best Practices
  • Things to Avoid
  • Quick Reference

Written by Rahul · Frontend Engineer at Google · Updated 2025

I'm going to be real with you — this in JavaScript confused me for years. Even after working at Google for 3 years, I still occasionally get tripped up. The problem isn't that this is complicated. The problem is that people try to memorize rules instead of understanding the one simple principle: this is determined by how a function is called, not where it's defined.

The 5 Rules of "this" — In Order of Priority

Rule 1: new Binding (Highest Priority)

function User(name) {
  this.name = name; // "this" = the newly created object
}
const rahul = new User("Rahul");
console.log(rahul.name); // "Rahul"

When you use new, JavaScript creates a fresh object and sets this to that object. Always.

Rule 2: Explicit Binding — call, apply, bind

function greet() {
  console.log(`Hello, ${this.name}`);
}

const user = { name: "Rahul" };

greet.call(user);    // "Hello, Rahul"
greet.apply(user);   // "Hello, Rahul"

const bound = greet.bind(user);
bound(); // "Hello, Rahul"

call and apply invoke immediately. bind returns a new function with this permanently set.

Rule 3: Implicit Binding — Object Method

const user = {
  name: "Rahul",
  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

user.greet(); // "Hello, Rahul" — this = user (the object before the dot)

The object before the dot becomes this. Simple.

Rule 4: Default Binding — Standalone Function

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

showThis(); // window (browser) or global (Node.js)
// In strict mode: undefined

Rule 5: Arrow Functions — Lexical "this"

const user = {
  name: "Rahul",
  greet: () => {
    console.log(this.name); // ❌ undefined! Arrow functions don't have their own "this"
  },
  greetCorrect() {
    const inner = () => {
      console.log(this.name); // ✅ "Rahul" — inherits from greetCorrect
    };
    inner();
  }
};

Arrow functions don't have their own this. They inherit this from the enclosing scope at definition time.

The Classic Pitfall — Losing "this" in Callbacks

This is the #1 bug I see in React codebases:

class Button extends React.Component {
  constructor() {
    super();
    this.state = { count: 0 };
  }

  handleClick() {
    // ❌ "this" is undefined here when used as callback!
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    // The problem: handleClick is passed as a callback
    // When React calls it, there's no object before the dot
    return <button onClick={this.handleClick}>Click</button>;
  }
}

Three fixes:

// Fix 1: Bind in constructor
constructor() {
  this.handleClick = this.handleClick.bind(this);
}

// Fix 2: Arrow function in class field (most common)
handleClick = () => {
  this.setState({ count: this.state.count + 1 });
};

// Fix 3: Arrow function in JSX (creates new function each render — avoid)
<button onClick={() => this.handleClick()}>Click</button>

Real Production Issues

Issue 1: Event Handler "this" in Vanilla JS

const controller = {
  element: document.getElementById("btn"),
  message: "Clicked!",

  init() {
    // ❌ "this" inside handler is the DOM element, not controller
    this.element.addEventListener("click", function() {
      console.log(this.message); // undefined
    });

    // ✅ Fix with arrow function
    this.element.addEventListener("click", () => {
      console.log(this.message); // "Clicked!"
    });
  }
};

Issue 2: setTimeout Losing Context

const api = {
  data: null,
  fetch() {
    setTimeout(function() {
      // ❌ "this" is window here
      this.data = "loaded";
    }, 1000);

    setTimeout(() => {
      // ✅ Arrow function preserves "this"
      this.data = "loaded";
    }, 1000);
  }
};

Issue 3: Destructured Methods

const user = {
  name: "Rahul",
  greet() { return `Hi, ${this.name}`; }
};

// ❌ Destructuring loses "this" context
const { greet } = user;
greet(); // "Hi, undefined"

// ✅ Keep the reference
user.greet(); // "Hi, Rahul"

Best Practices

  1. Use arrow functions for callbacks — they inherit this and prevent 90% of bugs
  2. In React, use hooks — functional components with hooks eliminate this entirely
  3. Never rely on default binding — always use strict mode ("use strict")
  4. Use arrow functions in class fields for methods that will be passed as callbacks
  5. When in doubt, console.log(this) — seriously, just log it

Things to Avoid

  • ❌ Don't use arrow functions as object methods (they won't have the right this)
  • ❌ Don't use .bind() in render methods (creates new function every render)
  • ❌ Don't mix this patterns — pick one approach per codebase

Quick Reference

Call Style"this" Points To
new Foo()New object
foo.call(obj) / foo.apply(obj)obj
obj.foo()obj
foo()window / undefined (strict)
() => {}Enclosing scope's this

Related Articles

MediumFrontend Engineering

System Design #12: Design a Multi-Step Form Wizard

7 min read
MediumFrontend Engineering

Mastering Senior-Level JavaScript Interview Concepts

2 min read
MediumFrontend Engineering

System Design #9: Design a Collaborative Text Editor

9 min read

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Table of Contents

  • The 5 Rules of "this" — In Order of Priority
  • Rule 1: new Binding (Highest Priority)
  • Rule 2: Explicit Binding — call, apply, bind
  • Rule 3: Implicit Binding — Object Method
  • Rule 4: Default Binding — Standalone Function
  • Rule 5: Arrow Functions — Lexical "this"
  • The Classic Pitfall — Losing "this" in Callbacks
  • Real Production Issues
  • Issue 1: Event Handler "this" in Vanilla JS
  • Issue 2: setTimeout Losing Context
  • Issue 3: Destructured Methods
  • Best Practices
  • Things to Avoid
  • Quick Reference

Series

View all Frontend Engineering articles →

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.