JavaScript Arrow Functions and Closures

ES6 introduced a new syntax for functions, the so-called Arrow Functions. They are more concise and usually a better way of describing functions. Let’s see how they work:

https://gist.github.com/vmarchesin/72e6cf8a6836ddcf1f06284b1d76164d

By default the arrow function is anonymous, so you need to assign it to a variable if you want to call it later. The same could be done using the function keyword.

Cool! But why should I use it? For starters, it looks better, doesn’t it? Take a look at how my code looks before and after using arrow functions.

https://gist.github.com/vmarchesin/df50cb8692918557379b54aa03cd3e05

Looks a lot better now! Take a good look and you’ll notice that I no longer need to use the return keyword. If you omit the brackets, the value is automatically returned! This is particularly useful when you use inline functions, or when passing callbacks.

If you omit the brackets, the value is automatically returned!

What about Closures?

OK, so you agree that the code looks cleaner. But that’s not enough to convince you to start using the arrow function syntax. Well, there’s a hidden benefit to this: it solves some closure problems!

A closure is the combination of a function and the lexical environment within which that function was declared.

Let’s create a talking dog that barks his own name! Oh the wonders of coding…

https://gist.github.com/vmarchesin/12aeffeaeeeb663ad8bbaa9402349747

Ok, so now if we run the code above we get a nice response:

rex.bark() // 'Woof, my name is Rex'

But in the process of training your now world famous talking dog you want to teach him the sitAndBark method, where he is only allowed to bark after one second. And… it doesn’t work.

rex.sitAndBark() // 'Woof, my name is '

What happened? Here we have closures doing their work. The setTimeout argument function has its own lexical scope, meaning you are trying to access this.name inside this new function now. Since it does not have a name property, the value resolves to undefined .

How do we solve it? Well, we could use the bind method to bind the class lexical scope to the argument function.

https://gist.github.com/vmarchesin/8c3d2763f3b19598e24c4d6182f5431f

Now this.name works as we intended.

rex.sitAndBark() // 'Woof, my name is Rex'

Let’s introduce the arrow function syntax now!

https://gist.github.com/vmarchesin/60642a26484006dc400366e31524c619

And it works!

rex.sitAndBark() // 'Woof, my name is Rex'

What happened here? This works because arrow functions don’t have a separate this . When trying to access this inside an arrow function, since they don’t have their own lexical scope defined, it’ll fall back to the previous scope, which is the class scope in this case. A much better approach than having to bind all your functions!

Arrow functions don’t have a separate this . When trying to access this inside an arrow function it’ll fall back to the previous scope, since they don’t have their own lexical scope defined.

Now that you are convinced, you are probably writing your own arrow functions while reading this. You’ll start using them everywhere and soon your code will look cleaner than ever. But…

DON’T USE ARROW FUNCTIONS EVERYWHERE!

Wait, why? They’re cleaner, and they solved all your closure problems. Didn’t they? Well, not all of them…

If you read the first paragraph of this article you’ll see that I said arrow functions are more concise and usually a better way of describing functions. If you don’t know what you’re doing you’ll do more harm than good. Take a good look at this example:

https://gist.github.com/vmarchesin/7e0641334d9397854c109e1c763ff1a7

In the example above there’s a declaration for a Array.prototype.first method, that returns the first element in the array. If you mindlessly use arrow functions without understanding closures, you’ll end up with something like this.

The second example doesn’t work, and could lead to unpredictable results. The syntax is correct, and in theory both examples do the same thing: return the element in the first position. But since arrow functions don’t have their own lexical scope defined, this will reference whatever is the previous scope which could be anything from another function to the global scope or window object.

The first example works because using the function keyword assigns the proper lexical scope to the function, and this will reference the array itself correctly.


What’s the conclusion?

Arrow functions are here to stay. They make functional programming code (or any code actually) look cleaner. They solve closure problems with readable and minimal syntax. They rescue puppies from burning buildings. In short, they’re awesome.

Just one bit of advice:

When using arrow functions mind the correct use of closures, and always have in mind the scope you are working with.

Even if you always use arrow functions because they look better, never forget that they don’t solve all your problems. Sometimes going back to the basics is the better solution.