Future JavaScript #1 — Arrow Functions

A series exploring next generation JavaScript syntax

Arrow functions are a new addition to the language that is supposed to be an alternative to the traditional functions, in some cases.

They are very simple and powerful, but with great power comes great responsibility, so you should know exactly when to and when not to use them.

In this guide I am going to cover several parts that I think are important for a complete understanding of arrow functions:

Syntax

What is different (compared to traditional functions)

Use cases

Rules

When to use / When not to use

Syntax

We all know and used the traditional function syntax a million of times:

function() {}

Let’s see what the new syntax looks like:

() => {}

You might think that it’s not worth using the new syntax, just to get rid of the `function` keyword.

Well, that’s not the only difference, keep reading.

What is different

Arrow functions have different logic compared to traditional ones. They have their advantages and disadvantages, and it’s important to understand them. Otherwise they might be very confusing to use.

Let’s go quickly through some points, to make sure you know the difference.

Arguments

Don’t rely on them, they are not exposed. It’s not good practice to rely on them anyway. Just use rest parameters (covered in a future guide).

this

Arrow functions take the context of the surrounding code. It’s inherited from the enclosing scope.

We all know that for traditional functions the context depends on where they are invoked.

For arrow functions the context depends on where they are declared.

call / apply / bind

Since the arrow functions take the surrounding context, these won’t really make a difference. Can still be used to pass parameters, but won’t change the context.

Prototype

Arrow functions don’t have a `prototype` property.

Constructor

Arrow functions cannot be used as constructors. For that just use traditional functions, they’re well known and familiar to everyone. Or better yet, use class.

Can’t be named

You can use arrow functions only as anonymous functions. Or said in a different way, only use as function expressions, not as declarations.

// NOfunc() => {}

// YESconst func = () => {};

No hoisting

Since arrow functions can be used only as expressions, there is no hoisting. Meaning that you can use it, only after it has been assigned. On the contrary, traditional function declarations are hoisted and can be used before the actual declaration.

Use cases

Let’s go through some examples on how you can actually use arrow functions. Let’s also see how a traditional function would be used compared to an arrow function, if comparable at all.

IIFE

Calling a function immediately after declaring it is a good practice for providing scope and not polluting the global object. The same can be achieved with arrow functions.

Just don’t forget to surround it with parenthesis. It looks confusing without ones.

// ES5(function() { ...})();

->

// ES6(() => { ...})();

// NO(() => {}());

Shorthand

The shorthand syntax is something you will fall in love with. It’s super conscious and easy to read and saves you some code. Essentially, you skip the parenthesis, and the `function` and `return` keyword.

// ES5array.map(function(x) { return x * x });

->

// ES6array.map(x => x * x);

Remember:

you can skip the return statement only if using them on one line

use it only when you have one statement (which will be returned)

Class

Since the arrow function uses the surrounding context it’s safe to use it as a way to bind the function to the context of the class. No more worries when passing it as callback.

Async

Async Functions. This is a great and powerful new concept as well. Essentially, you use them when you have a Promise that needs to be resolved or rejected. By using them we don’t have to pass callback functions and the code looks much cleaner. (Stay tuned for a guide on these soon)

const getter = async (url) => { return await http.get(url);};

Returned functions

JavaScript‘s power comes from its functional nature, the fact that functions are first-class objects. Which means you can return them. And that’s a powerful pattern that is used often. You can use arrow functions to make it look even more impressive.

Rules

There are certain rules that, if followed, will make your life easier when using arrow functions.

One line

Skip the curly braces and the return statement. Skipping the `return` statement works only for single expression though, so be careful to not forget it otherwise.

array.map(x => x * x);

If you have anything other than a single expression, use within a block.

array.map(x => { if (typeof x === “number”) return x * x });

Multiple lines

Use with the curly braces and explicit return. Works like traditional functions, if you don’t use the `return` statement, the returned value is undefined.

array.map(x => { if (x % 2 === 0) return x; return x * x;});

No parameters

Use with parenthesis. Using it without ones will break it.

let counter = 0;

array.forEach(() => { counter += 1;});

One parameter

Skip the parenthesis. Feel free to use them, but they are not needed and it looks better without ones.

let container = [];

array.forEach(value => { container.push(value);});

Multiple parameters

Use with parenthesis. If not used it actually thinks that we are passing one parameter and one arrow function, separated by a comma. So if you have two or more parameters, always wrap them in parenthesis.

let obj = {};

array.forEach((value, index) => { obj[value] = index;});

Returning an object

Surround with parenthesis. Object literal and arrow function both use blocks, so if you want to return an object with the shorthand syntax, surround it with parenthesis.

array.map(x => ({ foo: x }));

Or returning an empty object:

const empty = () => ({});

Arguments

Don’t use with arguments. Prefer the rest parameters syntax, since it better shows your intentions and let’s admit it… it looks sexier.