6

I thought I understood the relationship between this and arrow functions but the following snippet is making me question my understanding.

let person = {
  name: 'Jim',
  sayName: () => {
    console.log(this.name);
  }
};

person.sayName();

I understand that arrow functions capture the this value of the enclosing context. I was expecting this would be the object but instead it is Window.

Can someone help me understand why this is the case?

Tekeste Kidanu
  • 1,480
  • 2
  • 12
  • 19
  • 1
    In your example `this` will be undefined if you want to get the value of name either use the normal function syntax **or** reference the object name so it's `person.name` – Amr Aly May 20 '17 at 01:40
  • 3
    An `Object` literal doesn't create an enclosing context. Only the body of a normal function does. –  May 20 '17 at 06:37

3 Answers3

11

Your understanding of arrow functions is mostly correct: Arrow functions have a lexical this and its value within the arrow function is determined by the surrounding scope.

You probably assume that this gets a different value within the person object literal. This is not the case.

So let's see what this refers to in your (global) scope:

console.log(this === window); // true

let person = {
  name: 'Jim',
  test: console.log(this === window), // true
  sayName: () => {
    console.log(this === window); // true
  }
};

person.sayName();

As you can see, when the arrow function assigned to sayName is created, this refers to the window object.

Community
  • 1
  • 1
le_m
  • 15,910
  • 7
  • 55
  • 65
7

TLDR;

Think of it this way, "if I used non arrow function, what would be this" From that you can then recall that this in an arrow function would be the more outer scope this compared to its counterpart.

Example

let arrow = {
  test: () => {
    console.log('arrow: this === window...', this === window);
  }
};

let nonarrow = {
  test: function() {
    console.log('non-arrow: this === window...', this === window);
  }
};

arrow.test()
nonarrow.test();
EyuelDK
  • 2,464
  • 2
  • 14
  • 25
4

There is no binding of "this", so here is a working version of what you tried:

let person = {
  name: 'Jimmy the Greek',
  sayName: (obj) => {
    console.log(obj.name);
  }
};

person.sayName(person);

More to read on Mozilla DEV.

scrat.squirrel
  • 2,982
  • 21
  • 27