Arrow Function Syntax

The next version of JavaScript - called ES2015 (née ES6) - has just shipped. It’s final, so there won’t be any semantic or syntactic changes. What there will be are plenty of great features that coming to a JavaScript engine near you. Soon.

Even for engines that don’t implement ES2015 yet, you can use Babel to compile lots of those features into valid ES5 (the previous generation of JavaScript). This lets you run code levering the new goodness in all modern browsers, Node.js and most other places where JavaScript is used.

I’m a programmer who uses functions like a preschooler uses glitter, so arrow functions is one of the features I’m really excited about. Here’s what I’ve learnt from reading the specification, reading forum discussions and testing things out in the Babel playground.

Writing less, saying more

An arrow function is mostly just a new way to express an old concept - a plain old JavaScript function expression. It replaces the old function(a, b) with the new, sleeker (a, b) =>.

A ‘real world’ example..

As part of the ‘vanity metrics’ module for your company (hey, everyone’s got to have something to show the board, right?), you have a function that summarises the total contributions from all of your most active community members from your company’s site.

Here’s how we might refactor some old code that uses .map, .filter and .reduce.

var users = [
    { screenName: 'hughford', posts: 3 },
    { screenName: 'benvan',  posts: 100 },
    { screenName: 'tahir', posts: 130 }
];

var totalPostsByActiveUsers = users
    .map(function(user){ return user.posts })
    .filter(function(posts){ return posts > 50 })
    .reduce(function(a, b){ return a + b });

Becomes:

var totalPostsByActiveUsers = users
    .map((user) => { return user.posts })
    .filter((posts) => { return posts > 50 })
    .reduce((a, b) => { return a + b });

Just by replacing the function(...) with (...) =>, we’ve cut down the visual noise a little. The contents of the function body - the part between { and } - remain the same.

Refining further with AssignmentExpression

As you can see in the last example, you can use the same function body for new arrow functions as you could for function expressions. In the specification, this is called the FunctionBody syntax, and the engine will use this whenever it sees a { straight after the =>.

There’s an alternative you can use for your arrow function’s bodies. If you drop the { and the }, you can use whatever you’d normally put on the right-hand side of an assignment. This alternative form is called an AssignmentExpression.

So, since these are syntactically valid assignments:

var posts = user.posts;
var postsIsGreaterThan50 = posts > 50;
var aPlusB = a + b;

You can also use those exact same expressions - user.posts, posts > 50 and a + b - for your function bodies:

var totalPostsByActiveUsers = users
    .map((user) => user.posts)
    .filter((posts) => posts > 50)
    .reduce((a, b) => a + b);

Single parameter functions

One final little tweak to our example. In the special case where we have a function with a single parameter (also known as unary functions), we don’t even need the parentheses around the parameter list. That lets us refactor one last time, and get:

var totalPostsByActiveUsers = users
    .map(user => user.posts)
    .filter(posts => posts > 50)
    .reduce((a, b) => a + b);

That’s a pretty significant (if superficial) improvement, to my mind. Once you’re used to it, it’s easier to see the business logic rather than having to visually filter out language boilerplate. Less “can’t see the wood for the trees”.

If this is new to you, it might also look quite alien. Don’t worry, that feeling goes away. Pinky promise.

Choosing between AssignmentExpression or FunctionBody

So which form should you use - the shorter AssignmentExpression version, or the longer and more traditional FunctionBody?

My 2p is to go for the AssignmentExpression when you don’t need the power of multiple statements is the best shout. The terseness of it might look odd for a while, but it gets normal fast.

If you do need multiple statements, you’ll have to use a FunctionBody; there’s no choice.

Objection!

Readers that have had their Weetabix might have noticed there’s a gotcha lurking in the way the engine decides whether you’re using a FunctionBody or an AssignmentExpression.

If JavaScript uses the presence of { after the => to tell if we mean to use an old-school style FunctionBody, what if we want use an object literal as the AssignmentExpression?

After all, when we write an object literal and assign it to a variable, we can have a { as the first thing on the right-hand side of the equation:

var user = { screenName: 'hughford', posts: 3 };

But if you try to use this as the body to an arrow function, it’ll expect that the opening { is the start of a regular FunctionBody, and error when it sees that the contents doesn’t make any sense.

// When you write this...
var newUser = name => { screenName: name, posts: 0 };

// The engine sees it as equivalent to this, which can't be right!
var newUser = function(name){ screenName: name, posts: 0 };

If you want to use the AssignmentExpression for the function body while using object literals, your best bet is to wrap the whole function body in ( and ). These extra parentheses don’t do anything, really. They just make it clear to the engine that you mean an AssignmentExpression, not a FunctionBody.

var newUser = name => ({ screenName: name, posts: 0 });

More than skin-deep

In this post, we’ve got all of the new syntax under our belts. You could probably go out into the wild and start using them to tidy up your codebase - and I encourage you to at least play with these in the babel sandbox.

In the next post, we’ll be diving deep into the changes in behaviour that come with arrow functions - including what’s changed with this, why arguments is now outlawed (and what replaces it) and some very cool function name inference.