JavaScript: this Keyword and Context

Learn what 'this' refers to in different situations and how to control it with call, apply, and bind.

What is this?

this is a special keyword that refers to an object. Which object it points to depends entirely on how and where the function containing it is called, not where the function is defined (except for arrow functions).

this

this is resolved at call time, not at definition time, for regular functions.

  • The value of this is set each time a function is invoked
  • Different call patterns produce different this values
  • Arrow functions are the exception: they capture this from the surrounding scope at definition time
  • Understanding this is key to working with objects, classes, and callbacks correctly

this Depends on the Call

The same function logs different values for this depending on how it is called.

Global Context

At the top level of a script (outside any function), this refers to the global object, window in browsers,global in Node.js.

Global this

At the top level, this is the global object, the container for all global variables.

  • In a browser: this === window at the top level
  • In Node.js: top-level this is an empty module object, not global
  • In strict mode ("use strict"), this inside a plain function call is undefined, not the global object

Global Context

At the top level and in plain function calls, this points to the global object.

Function Context

When a regular function is called as a plain function (not as a method), this is the global object in non-strict mode, or undefined in strict mode.

Function Context

Plain function calls do not set a meaningful this, rely on explicit binding instead.

  • Non-strict: this defaults to the global object
  • Strict mode ("use strict"): this is undefined, accessing properties on it throws
  • ES modules run in strict mode automatically, so this inside module functions is undefined

Function Context in Strict vs Loose Mode

Strict mode makes this undefined in plain function calls, exposing accidental usage.

Method Context

When a function is called as a method of an object, using dot notation, this is set to the object before the dot.

Method Context

The object to the left of the dot at call time becomes this.

  • It is the call site that matters, not where the method is defined
  • The same function can serve as a method on different objects, getting a different this each time
  • Chained methods like obj.a.b() set this to obj.a (the object immediately before the call)

Method Context

this is determined by the object the method is called on, not where it was defined.

Event Handler Context

In a DOM event handler, this refers to the element that the listener is attached to, when using a regular function.

Event Handler this

The browser sets this to the DOM element that fired the event when using regular function handlers.

  • A regular function handler: this is the element (event.currentTarget)
  • An arrow function handler: this is inherited from the surrounding scope, NOT the element
  • Use a regular function when you need to reference the element via this inside the handler

Event Handler Context

Use a regular function when you need this to be the clicked element.

Arrow Functions and this

Arrow functions do not have their own this. They capture this from the enclosing lexical scope at the time they are defined, and it never changes.

Arrow Functions and this

Arrow functions inherit this from where they are written, a major reason to prefer them in callbacks.

  • Cannot be bound, called, or applied with a different this
  • Perfect for callbacks inside methods where you want to keep the method's this
  • Do NOT use arrow functions as object methods if you need this to be the object

Arrow Function Preserving this

The arrow inside setInterval captures this from start(), which is timer.

Explicit Binding: call()

call() invokes a function immediately with a specified this value and arguments passed one by one.

call()

call() lets you borrow a method and run it with a different this on the spot.

  • Syntax: fn.call(thisArg, arg1, arg2, ...)
  • Executes immediately, does not return a new function
  • Useful for borrowing methods from one object and using them on another

call() Example

Borrow introduce and run it with different objects and arguments.

Explicit Binding: apply()

apply() works exactly like call(), but accepts arguments as an array instead of individually.

apply()

Use apply() when your arguments are already in an array or array-like object.

  • Syntax: fn.apply(thisArg, [arg1, arg2, ...])
  • Executes immediately, just like call()
  • Classic use: Math.max.apply(null, numbersArray) to spread an array into Math.max

apply() Example

Pass an existing array directly as arguments, no need to unpack manually.

Explicit Binding: bind()

bind() returns a new function withthis permanently set to the given value. The new function can be called later.

bind()

bind() creates a reusable version of a function with a fixed this.

  • Syntax: const bound = fn.bind(thisArg, ...partialArgs)
  • Does NOT execute immediately, returns a new function
  • Calling bind() a second time on an already-bound function has no effect
  • Ideal for passing methods as callbacks without losing their object context

bind() Example

Lock this for a delayed callback, and use partial application to pre-fill arguments.

call vs apply vs bind

All three methods let you set this explicitly, but they differ in when and how the function runs.

MethodExecutesArgumentsReturns
call(ctx, a, b)ImmediatelyListed individuallyFunction result
apply(ctx, [a, b])ImmediatelySingle arrayFunction result
bind(ctx, a, b)Later (you call it)Listed individually (partial ok)New bound function

Lost Context and Solutions

Context is "lost" when a method is detached from its object before being called, most commonly when passing a method as a callback. The function then runs without a receiver, and this reverts to the global object or undefined.

Lost Context

Extracting a method from its object breaks the this binding.

  • Common cause: passing obj.method as a callback (e.g. to setTimeout or an array method)
  • Fix 1: use .bind(obj) when passing the callback
  • Fix 2: wrap in an arrow function: () => obj.method()
  • Fix 3: store const self = this before an old-style callback (legacy pattern)

Lost Context and Fixes

Detaching increment breaks this, bind or an arrow wrapper restores it.

Knowledge Check

1. What does 'this' refer to inside a regular function called in non-strict mode in a browser?

2. What does 'this' refer to inside a method called on an object?

3. How do arrow functions handle 'this'?

4. What is the difference between call() and apply()?

5. What does bind() return?

6. Why is 'this' lost when a method is passed as a callback?

7. Which is the best fix to preserve 'this' when passing a method as a callback?