What does 'this' refer to inside arrow functions that are defined inside IIFEs that are defined inside a method?

Viewed 57

What I understand is that arrow functions don't rebind this, so why does it refer to different objects depending on how it's invoked?

const foo = {
  speak() {
    (() => {
      console.log(this);
    })();
  }
};

foo.speak(); // Logs foo

const speak = foo.speak;

speak(); // Logs the global object

Thank you for your time!

3 Answers

Arrow functions preserve the lexical value of this. What this means is, the value of this depends on how the arrow function is defined and not on how the arrow function is invoked.

The inconsistent behavior you see here is because the inner arrow function is being "defined" every time the function speak is being invoked. At that point of definition, the arrow function captures the current value of this which is different for foo.speak() and speak().

As a side note, this seems like JavaScript trivia. I wouldn't expect a "real" codebase to have this kind of snippets.

The arrow function is being defined and executed only when and each time speak is called. The first time you call it is as a method on foo, therefore this is bound to foo. The second time you call it, this is the window. Compare to this version:

const foo = {
  speak: () => {
      console.log(this);
  }
};

foo.speak(); 

const speak = foo.speak;

speak(); 

Where the speak function is the arrow function and therefore the this is bound immediately to the window object for both calls.

I believe what's happening is, when you assign the function to the const variable it loses it scoping.

When you call foo.speak(), the speak function is running in the context of foo, whereas when you run speak() after assigning the foo.speak function to the const variable, the function is running in the context of the global (window) object.

MDN states:

the value of this is determined by how a function is called (runtime binding). It can't be set by assignment during execution, and it may be different each time the function is called

Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

Related