100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

How Does the `this` Keyword Work in JavaScript?

Learn how JavaScript resolves `this` by call site, why arrow functions differ, and how to avoid the most common `this` bugs.

mediumQ30 of 224 in Web Development Est. time: 5 minsLast updated:
Open Code Lab

Expected Interview Answer

The value of `this` in JavaScript is not fixed by where a function is defined but by how that function is called at runtime — its binding is determined by the call site, except for arrow functions, which inherit `this` lexically from their enclosing scope.

When a function is called as a method (`obj.method()`), `this` binds to the object before the dot. When called as a plain function (`fn()`), `this` is `undefined` in strict mode or the global object in sloppy mode. When called with `new`, `this` is a freshly created object linked to the constructor prototype. When called via `call`, `apply`, or `bind`, `this` is explicitly set to whatever is passed as the first argument. Arrow functions break this pattern entirely: they have no own `this` binding and instead capture `this` lexically from the surrounding code at the time they are defined, which is why they are commonly used inside callbacks to preserve the outer `this`. Losing track of the call site — for example, passing a method as a bare callback — is the single most common source of `this` bugs.

  • Enables flexible, reusable method definitions independent of a fixed object
  • Arrow functions solve the classic callback `this`-loss problem cleanly
  • call/apply/bind give explicit, deliberate control over binding
  • Understanding call-site rules eliminates an entire class of runtime bugs

AI Mentor Explanation

The word “captain” refers to whoever is currently leading the side, not a fixed person tied to the word itself — swap the leader before the toss and “captain” now means someone new. That is exactly how `this` resolves: it depends on who is standing at the call site when the function runs, not on where the function was written. A team announcer using a fixed script (an arrow function) instead keeps referring to whichever captain was named when the script was written, ignoring later changes. This call-site-versus-lexical distinction is the whole story of `this` binding.

Step-by-Step Explanation

  1. Step 1

    Find the call site

    Look at how the function is actually invoked, not where it was defined.

  2. Step 2

    Apply the binding rules in order

    Check `new` binding, then explicit call/apply/bind binding, then implicit method-call binding, then default binding.

  3. Step 3

    Special-case arrow functions

    Arrow functions ignore all call-site rules and inherit `this` lexically from the enclosing scope.

  4. Step 4

    Verify against strict mode

    Default binding gives `undefined` in strict mode versus the global object in sloppy mode.

What Interviewer Expects

  • Correctly explains call-site-based resolution, not definition-site
  • Distinguishes implicit, explicit, new, and default binding
  • Explains why arrow functions behave differently (lexical `this`)
  • Can identify `this` bugs in a bare callback / detached method example

Common Mistakes

  • Claiming `this` depends on where a function is defined (true only for arrow functions)
  • Forgetting that passing a method as a callback detaches it from its object
  • Assuming `this` is always the global object regardless of strict mode
  • Confusing arrow function lexical `this` with regular function default binding

Best Answer (HR Friendly)

In JavaScript, `this` depends on how a function gets called, not where it was written. If you call it as `obj.method()`, `this` is `obj`. If you just pass the function around and call it plain, you can lose that connection — that is a classic bug. Arrow functions solve this by always using the `this` from the surrounding code, which is why they are so common in callbacks.

Code Example

Call-site binding vs arrow function lexical binding
const user = {
  name: 'Ava',
  greetRegular: function () {
    console.log(`Hi, I’m ${this.name}`) // 'this' = whoever calls it
  },
  greetArrow: () => {
    console.log(`Hi, I’m ${this.name}`) // 'this' = enclosing scope, NOT user
  },
}

user.greetRegular() // "Hi, I’m Ava" (method call binding)
const detached = user.greetRegular
detached() // "Hi, I’m undefined" (default binding, lost the object)
const bound = user.greetRegular.bind(user)
bound() // "Hi, I’m Ava" (explicit binding restores it)

Follow-up Questions

  • Why does a method passed as an event handler often lose its `this` binding?
  • How does `bind` differ from `call` and `apply`?
  • What is `this` inside a class constructor versus a class method used as a callback?
  • How does `this` behave inside a regular function nested inside an arrow function?

MCQ Practice

1. What determines the value of `this` inside a regular (non-arrow) function?

`this` for regular functions is resolved dynamically based on the call site, not lexical position.

2. How does an arrow function determine `this`?

Arrow functions have no own `this`; they capture it lexically from where they were defined.

3. What happens to `this` when a method is passed as a bare callback (e.g., `setTimeout(obj.method)`)?

Detaching a method from its object strips the implicit binding, falling back to default binding.

Flash Cards

What decides `this` in a regular function?The call site — how the function is invoked, not where it was written.

How does an arrow function get `this`?Lexically, inherited from the enclosing scope at definition time.

What is default binding?`this` falls back to `undefined` (strict mode) or the global object (sloppy mode).

How do you force a specific `this`?Use `call`, `apply`, or `bind` to explicitly set it.

1 / 4

Continue Learning