Arrow function: What is this?

Jan 6, 2019 · 5 min read
Image for post
Image for post

With the arrival of the ES6 (ES2015) standard, we now have a whole 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 will serve as the extensions to or the improvements of the existing syntaxes and features to make developers’ lives easier.

Among those new syntaxes, I’ve found the “arrow function” feature so useful 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, which allows me to implement more succinct, readable code.

If you are completely unfamiliar with an arrow function, it is just a normal Javascript function with the =>symbol serving as a syntactic sugar for easily defining the function, hence its name. You can easily define an arrow function:

Notice how I’ve replaced the function keyword with the => symbol, removed the curly braces, and assigned the entire expression () => console.log('foo'); to foo, which is a “constant” (const is also part of the ES6 specification. You can check the MDN documentation for more information. 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.

With the brief introduction to 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 this in an arrow function is interpreted differently than in a “normal” function. Namely, this within an arrow function is defined with a “lexical scope” whereas this within a “normal” function, or a function defined with the functionkeyword, is defined with a “dynamic scope”.

Put more simply, an arrow function’s this has already been determined when the function is written while a “normal” function’s this will be 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 people’s names along with their random greetings by referencing the relevant method and object (i.e. the getRandomElement method and the greetings array) from within the callback function for the forEach method. You may also notice how the 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, 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.

Image for post
Image for post

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 undefined 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 we can achieve with 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 be aware of is “how the code is written”; the callback function will be 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 on line 10 of the arrow method body (i.e.this in this.people). Even if the callback function is executed later, its context remains the same as when it was defined. It doesn’t change as in 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.

Image for post
Image for post
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.

Image for post
Image for post

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




Get the Medium app
