Arrow Functions and This

this keyword in arrow function

Arrow functions have a lexical this which means that the value of this inside the function is the same as the value of this outside the function.

It does not mean that this points to an object containing all the variables from outside the function.

const anObject = {
aValue: "example value",
aMethod: function() {
console.log("aMethod", this.aValue);

const arrow = () => {
console.log("arrow", this.aValue);
}

arrow();
}
}

anObject.aMethod();

const copyOfAMethod = anObject.aMethod;
copyOfAMethod();

The this keyword not working with arrow functions

There's not really enough context to give you a good answer, but one thing stands out. Arrow functions maintain scope, so this inside function click() and const click may well be different. In the ES6 version, this will refer to whatever was this during the closure creation, which may not be what you want.

Arrow Functions at MDN clears it up:

An arrow function does not have its own this.

…Which means that this will be inherited from the declaring scope.

ES6 arrow functions aren't just a new way of declaring functions, and there's nothing inherently wrong with function myFunction(...) syntax, nor is it going away. Arrow functions avoid some verbosity when passing a function as an argument (e.g. to forEach) and avoid the need to rebind a function to a different this in some cases. Converting all function declarations to arrow syntax is not an upgrade.

Arrow Functions and This

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

Longer answer: Arrow functions
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);
}
};

Fat arrow or function() with this keyword

Use the traditional function declaration, because it will decouple your handleUpdate() function from the UI, so:

  • you can implement it in a totally different file and reuse it wherever you need its functionality
  • the function does not need to have an input variable defined in the context where it's used

If you're still doubting that's the way to go, VueJS also uses traditional functions in several places, having stuff that's actually not working if fat arrow functions were used:

From Vue's official docs:

Don’t use arrow functions on an options property or callback, such as created: () => console.log(this.a) [...]. Since arrow functions are bound to the parent context, this will not be the Vue instance as you’d expect, often resulting in errors such as Uncaught TypeError: Cannot read property of undefined.

So yeah, don't worry about using traditional functions, especially if you can explain the why's behind your choice.



Related Topics



Leave a reply



Submit