3

MDN presents the following two examples of arrow functions

Example 1

var adder = {
  base: 1,

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base: 2
    };

    return f.call(b, a);
  }
};

console.log(adder.addThruCall(1)); // 2

Example 2

'use strict';
var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log(this.i, this);
  }
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}

Question

  • this.base in Example 1 points to adder.base
  • this.i from property b in Example 2 resolves to undefined

If arrow functions do not have a this value, should not this.base also resolve to undefined?

Magnus
  • 6,791
  • 8
  • 53
  • 84
  • 1
    In the first example `this` inside the arrow function is lexically scoped. That's what it means "not having a `this`". – elclanrs Jan 22 '18 at 01:02
  • 1
    *"arrow functions do not have a this value"* - this is not entirely correct, arrow functions simply treat `this` like any other variable without special meaning (lexical binding) while traditional functions have this special exception for `this`. – le_m Jan 22 '18 at 01:04
  • @le_m A lexical binding, yes, but the name "`this`" only resolves because they do not have their own `this` value (which would be chosen over the parent scope). – Bergi Jan 22 '18 at 01:20

2 Answers2

2

In example 1, the arrow function f is created inside of the function addThruCall inside of adder. That means this inside of f will point to addThruCall's this, which is adder.

In example 2, the arrow function b is not inside of any normal function, so its this doesn't point anywhere.

It's not that arrow functions don't have a this value, it's that arrow functions will not change the this value from where they are created.

EKW
  • 2,059
  • 14
  • 24
  • They really do not have a `this` value. It resolves to the parent scope's `this` value, and when that changes the "arrow function's `this`" will reflect this change. It's not stored when they are created. – Bergi Jan 22 '18 at 01:21
2

Arrow functions have a "this", it's whatever "this" is in the current scope when you define them.

In you second example, in arrow function b(), since you have no particular parent scope defining "this", "this" is pointing to "Window" (in a browser context)

Also in your second example, in named function c(), function()... introduces a scope, and this is undefined by default.

So what you see is completely expected. However, as you can see, "this" is complicated to master, so good code style suggest to avoid it if you can. In this case, you may want to use a closure.

Interesting read about this in this other question: How does the "this" keyword work?

Offirmo
  • 18,962
  • 12
  • 76
  • 97
  • Thanks for all the solid answers, hard to pick one. After having understood a bit more, I just wanted to add the following for the benefit of future visitors: 1) In functions, `this` refers to the object the function is executing in. Exceptions to this rule include: Closures/nested functions (scope is lost, `this` refers to global object); arrow functions (`this` refers to enclosing context's `this` value); when otherwise specified with `bind`, `call`, `apply`; when function is called in global context (`this` refers to global object). – Magnus Jan 22 '18 at 18:58
  • Continuation of above comment: In Example 1, the arrow function's `this` value, is the `this` value of the enclosing function (as arrow functions do not have their own `this` value). The normal rule applies to the enclosing function (`this` refers to the adder object, as adder called the `addThruCall` function). In Example 2, also being an arrow function, `this` again refer to the `this` value of the enclosing context. Here though, the enclosing context is the global context (as there is no outer function). Thus, `this` in the arrow function equals the global object. – Magnus Jan 22 '18 at 19:02