Skip to main content

Function context

The function context is the object that the keyword this refers to inside a function while it runs. The main rule: the context is determined at the moment the function is called, not at the moment it is declared.

Theory

TL;DR

  • this is a reference to the object in whose context the function is currently running.
  • The value of this depends on how the function is called, not on where it was declared.
  • A plain call: the global object (window in a browser) or undefined in strict mode.
  • A method call obj.method(): the context becomes obj.
  • A call through new: the context becomes the newly created object.
  • call, apply, bind: the context is set manually.
  • Arrow functions have no this of their own and take it from the surrounding scope.

Quick example

javascript
function showThis() { console.log(this); } showThis(); // in a plain call the context is the global object

In a browser in sloppy mode:

javascript
this === window;

In Node.js inside a regular function in strict mode:

javascript
this === undefined;

The context depends on the way the function is called

How we call the functionWhat this will be
Plain call func()The global object (window) or undefined in strict mode
Method call obj.method()The object obj
Through newThe newly created object
Through call / apply / bindThe object you specify manually
Inside an arrow functionthis is taken from the outer context (lexically)

A plain call, that is, the global context:

javascript
function test() { console.log(this); } test(); // window (or undefined in strict mode)

A call as a method of an object:

javascript
const user = { name: "Alice", sayHi() { console.log(this.name); }, }; user.sayHi(); // "Alice"

Here this refers to the object user, because the function was called exactly as user.sayHi().

Losing the context

javascript
const user = { name: "Alice", sayHi() { console.log(this.name); }, }; const hi = user.sayHi; hi(); // undefined, this is lost

Why:

  • We passed a reference to the function, but not the object itself.
  • The call hi() is a plain call, without the user context.

The fix with bind:

javascript
const hi = user.sayHi.bind(user); hi(); // "Alice"

The same trap appears when a method is passed as a callback: setTimeout(user.sayHi, 100) or button.addEventListener("click", user.sayHi).

The context when calling with new

javascript
function User(name) { this.name = name; } const u = new User("Alice"); console.log(u.name); // "Alice"

Here this points to the newly created object (u). The new operator creates an empty object, makes it the context of the call and returns it, unless the function explicitly returns another object.

call, apply and bind

javascript
function greet() { console.log(this.name); } const user = { name: "Maria" }; greet.call(user); // "Maria" greet.apply(user); // "Maria" const boundGreet = greet.bind(user); boundGreet(); // "Maria"
MethodWhat it does
call(thisArg, arg1, arg2, ...)calls the function with the given this and comma-separated arguments
apply(thisArg, [args])the same, but the arguments are passed as an array
bind(thisArg)returns a new function with a fixed this, without calling it right away

Arrow functions and a summary

javascript
const obj = { name: "Alice", arrow: () => console.log(this.name), regular() { console.log(this.name); }, }; obj.arrow(); // undefined, this is the outer context, not obj obj.regular(); // "Alice"

What matters:

  • Arrow functions have no this of their own.
  • They "take" this from the surrounding lexical scope, that is, from where they were created.
  • Because of that, call, apply and bind cannot change this inside an arrow function.

Summary table:

SituationWhat this will be
Plain callwindow or undefined
Method of an objectThe object itself
newThe new instance
call, apply, bindThe object you specify manually
Arrow functionInherits this from outside

The function context is the "owner of the call": whoever calls the function becomes this.

Common mistakes

  • Believing that this is decided by where the function is declared. It is not, it is decided by where and how it is called.
  • Passing a method as a callback without binding it. setTimeout(user.sayHi, 100) loses the context. You need user.sayHi.bind(user) or an arrow wrapper () => user.sayHi().
  • Writing an object method as an arrow function. Then this points at the surrounding scope rather than the object, and this.name gives undefined.
  • Mixing up call and apply. call takes comma-separated arguments, apply takes an array.
  • Expecting bind to be overridable. A bound function cannot be rebound with another bind or with call: the first binding wins.
  • Forgetting about strict mode. Code in modules and classes is always strict, so a plain call there gives undefined, not window.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.