this binding in JavaScript: what decides its value at call time

The value of this is not fixed when a function is written but at every call. Four call forms produce four different results, plus one exception.
4 min read
Believemy logo

A method works perfectly, then you pass it as an argument and it breaks. Not a single line of the code changed. What changed is the way it is called.

That is the peculiarity of this in JavaScript: its value is decided not where the function is written, but where it is called. That resolution is known as this binding.


Definition

this binding is the rule that determines, at call time, which object the function will refer to as this. Four call forms exist, plus a fifth that escapes the rule entirely.

Call formWhat this holds
new Account()The freshly created object
account.introduce()The object written before the dot
introduce.call(account)The first argument supplied
introduce()undefined in a module, the global object otherwise
() => ...Whatever it was where the arrow was written

This two-column table reads top to bottom: the first form matching the call wins.

What this holds depending on the call formTwo-column table. new Account() gives the freshly created object, account.introduce() the object before the dot, introduce.call(obj) the first argument given, introduce() undefined inside a module, and an arrow function reuses the this of the code around it. The highlighted row is the detached call, which has lost its object.Call formWhat this holdsnew Account()The freshly created objectaccount.introduce()The object before the dotintroduce.call(obj)The first argument givenintroduce()undefinedin a module(…) => …The surrounding code's thisintroduce(): the method left its objectA call with no dot has no object to point at


The case that breaks, and why

JAVASCRIPT
const account = {
  name: "Believemy",
  introduce() {
    return this;
  },
};

console.log(account.introduce() === account); // true

const detached = account.introduce;
console.log(detached() === account);          // false

const bound = account.introduce.bind(account);
console.log(bound() === account);             // true

The method does not belong to the object, it is merely stored there. Taken out of its slot, it becomes an ordinary function called without a dot, and therefore without an object to point at. In a module, this holds undefined and any property read throws a TypeError.


The three ways to reset the binding

  • bind() returns a new function whose this is frozen. That is the answer when the function travels elsewhere.
  • call() and apply() call immediately while forcing this. They differ only in how arguments are passed.
  • The Arrow function has no this of its own: it reuses the one from where it was written, which solves the problem without thinking about it.
JAVASCRIPT
const timer = {
  name: "stopwatch",
  start() {
    setTimeout(() => {
      console.log("done: " + this.name);
    }, 10);
  },
};

timer.start(); // done: stopwatch
Good to know

With a classic function in place of the arrow, this.name would no longer point at the timer: the callback is called by the engine, with no object in front of it.


Frequently asked questions

Question

Why does my class method lose its this when passed as an argument?

Because passing object.method hands over the function alone, detached from the object. The fix is to pass object.method.bind(object), or to wrap the call in an arrow. Inside a class, declaring the method as an arrow field freezes the binding once and for all.


Question

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

None in the result. call() takes arguments one by one, apply() takes them in an array. Since Spread (...) arrived, apply() has lost almost all of its purpose, because fn.call(target, ...list) does the same thing more readably.


Question

Can an arrow function be rebound to another object?

No, and that is intentional. An arrow has no binding of its own, so bind(), call() and apply() have no effect on its this. That is exactly why it is reliable as a callback, and unsuitable as an object method or a constructor.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.