Arrow Functions and This

jason328 picture jason328 · Mar 1, 2015 · Viewed 14.6k times · Source

I'm trying out ES6 and want to include a property inside my function like so

var person = {
  name: "jason",

  shout: () => console.log("my name is ", this.name)
}

person.shout() // Should print out my name is jason

However, when I run this code console only logs my name is. What am I doing wrong?

Answer

Sean Vieira picture Sean Vieira · Mar 1, 2015

Short answer: this points at the nearest bound this - in the code provided this is found in the enclosing scope.

Longer answer: Arrow functions bind their this when they are created do not have this, arguments or other special names bound at all - when the object is being created the name this is found in the enclosing scope, not the person object. You can see this more clearly by moving the declaration:

var person = {
  name: "Jason"
};
person.shout = () => console.log("Hi, my name is", this);

And even more clear when translated into a vague approximation of the arrow syntax in ES5:

var person = {
  name: "Jason"
};
var shout = function() {
  console.log("Hi, my name is", this.name);
}.bind(this);
person.shout = shout;

In both cases, this (for the shout function) points to the same scope as person is defined in, not the new scope that the function is attached to when it is added to the person object.

You cannot make arrow functions work that way, but, as @kamituel points out in his answer, you can take advantage of the shorter method declaration pattern in ES6 to get similar space savings:

var person = {
  name: "Jason",
  // ES6 "method" declaration - leave off the ":" and the "function"
  shout() {
    console.log("Hi, my name is", this.name);
  }
};