Arrow function: What is this?

With the arrival of the ES6 (ES2015) standard, we now have a whose set of new, convenient syntaxes at our disposal when writing Javascript programs.

While some of the new syntaxes are designed to improve Javascript coding experience by offering entirely new features (e.g. Promise), most of them are designed as the extensions to or the improvements of the existing syntaxes and features, making developers’ lives easier.

Among those new syntaxes, I’ve found the “arrow function” feature to be so useful and brilliant that I often find myself writing the good old function keyword to start defining a function due to my muscle memory being activated, before replacing it with the little => symbol, allowing me to implement more succinct, readable code.

What is an arrow function?

If you are completely unfamiliar with an arrow function (which I would not imagine is the case, though, since you have read thus far), it is just a syntactic sugar that allows for easily creating and implementing functions in Javascript with the use of an arrow symbol (=>), hence its name.

Notice how I’ve replaced the function keyword with the => symbol, removed the curly braces, made the function one-liner, assigned the entire expression () => console.log('foo'); to foo, which is a “constant” (const is also part of the ES6 specification and I encourage you to check the detailed explanation on the MDN documentation if you are unsure about how it works. Basically it serves the same role as the var keyword, except that it’s scoped on a “block” level, and it cannot be reassigned nor redeclared. It also has to be initialized with a value when it’s declared).

The benefits of arrow functions will become apparent when they are used as a callback function as shown in the following example.

On the last line, note how I was able to omit the return keyword. This is because the arrow function knows to return an expression that comes after => when expressed as a one-liner.

We can even remove the parentheses around the function argument if there is only 1 argument provided.

What is this?

With a brief introduction to the arrow function completed, let’s now look at the main topic of this article, which is to understand what this refers to within an arrow function (yes, I used the title of this article to mean the thiskeyword in Javascript. My apologies if the title was somewhat geeky).

The reason we should care about the notion of this in a Javascript arrow function is that there is a significant difference in the way this is interpreted between the two notations. Namely, this within an arrow function is defined with a “lexical scope” whereas this within a “normal” function, by which I mean a function defined with the functionkeyword, is defined with a “dynamic scope”.

Put more simply, an arrow function’s this is determined already when the function is written while a normal function’s this is determined only when the function is executed.

(for more precise explanations, you might want to check this SO post)

Let’s look at the following program to make this point clearer.

Here, we are trying to output persons’ names along with their random greetings by referencing the relevant method and object (i.e. getRandomElement method and greetings array) from within the callback function for the forEach method. You may also notice how an object’s methods can be defined without the function keyword, which is also part of the ES6 specification. This is effectively the same as the following code, albeit with less typing involved.

If we run obj.normal() , the program will throw an error since the execution context (i.e. this) of the callback function for forEachis the Window object. This is due to the callback function being “dynamically” scoped as mentioned previously.

Since this is set to Window, which doesn’t have the getRandomElement function (method) defined, this.getRandomElement will return undefined , resulting in the error because we are providing undefined with parentheses and an argument as if we are trying to call a function, which it is not.

Before ES6, we had to get around this problem (or feature) of this referencing an undesirable object by using one of the following “tricks”.

  1. Cache the context this into a variable:

2. Use the bind method (Note that call or apply cannot be used here as they will actually invoke the function, rather than return it and provide the returned function as the forEach method’s callback function, which can be achieved by bind ):

3. Supply additional argument as context (if available)

As a developper, we all wonder why we have to go through these kinds of laborious process for a simple, yet quite common, task (i.e. iterating over a collection and doing something for each item within the collection).

With an arrow function, you don’t have to worry about the execution context being changed when a function is executed. All we have to pay attention to is “how the code is written”, by which I simply mean that we can treat the callback function as if it’s being run with the same context as its surrounding code.

Being lexically scoped, an arrow function shares the scope of its parent function even after the parent function has returned. It therefore has access to this defined on line 10 of the arrow method body (i.e.this in this.persons). Even if the function is executed later, its context remains the same as when it was defined. It doesn’t change as is the case for a dynamically defined function whose context depends uniquely upon how it’s invoked.

I hope the above example could give you a glimpse into the power of an arrow function. No longer will you find yourself becoming annoyed by mistyping the function keyword and watching an error displayed on the console.

Mistyping the “function” keyword

Everything in our life, though, seems to come with tradeoffs. And the expressive power of an arrow function is no exception.

From the next article, we will look at how an arrow function can play havoc with its sharp arrowhead (and what we can do to avoid it), starting from its behaviour within the forEach , $.each , and each methods.


Any comment or suggestion on how the article can be improved will be greatly appreciated!