DEV Community

Cover image for How to use arrow functions in JavaScript ES6
Rob Kendal {{☕}}
Rob Kendal {{☕}}

Posted on • Originally published at robkendal.co.uk on

How to use arrow functions in JavaScript ES6

JavaScript on a computer screen

I've been learning a lot about React lately, largely from the wonderful Fullstack React book. (Which I'd highly recommed, as well as following the team on their Twitter account, @fullstackreact).

One of the exciting parts of this journery is the liberal use of ES6 throughout the book. ES6 language features are a delight to use over and above the standard JavaScript language flavour and add some sound new tools and techniques to the language. However, one of the features I found particularly interesting was arrow functions.

I realise that I'm a little late to the party on this one as they're hardly a new and unknown feature, but I certainly found them intriguing and was a little confused at the different syntax required to use them. Hopefully, this guide will help me cement my own understanding, as well as help anyone who's looking to get to grips with arrow functions and their uses.

What are arrow functions?

Arrow functions (as per the MDN reference guide on arrow functions) are simply function statements with shorter syntaxes; they offer an alternative to the standard function construct, function (args) { // code stuff here; } and their primary advantage is in creating code clarity.

They do offer some more control over this, but for now, let's look at their shorter syntax and how they play a part in generating terser, more readable code.

How do we use them?

Glad you asked! There are three main ways you're likely to construct and use arrow functions so let's get going with some examples.

NB - in these examples, we'll imagine we're using an array of ice cream flavours like this:

const flavours = [chocolate, strawberry, vanilla, cherry, toffee];

Multiple-line body with explicit return

If your function spans multiple lines with several statements, you can write an arrow function like this:

const flavourLengths = flavors.map((flavour) => {
    const flavourLength = flavour.length;
    const flavourCapitalised = flavour.charAt(0).toUpperCase() + flavour.slice(1);
    return `${flavourCapitalised} is ${flavourLength} letters`; 
});
console.log(flavourLengths);
// prints -> ["Chocolate is 9 letters", "Strawberry is 10 letters", ...etc]
Enter fullscreen mode Exit fullscreen mode

Note that here we must include an explicit return statement. What's more, if you only have a single parameter, you can also omit the initial brackets like this:

const flavourLengths = flavours.map(flavour => {\
  // ...
);
Enter fullscreen mode Exit fullscreen mode

Single-line/-expression body with implicit return

If your function body only contains a single line, you can wrap it in brackets and ignore the return statement as it is implied.

const flavourLove = flavours.map(flavour => (
    'I love ' + flavour.toUpperCase() + ' ice cream!'
));
console.log(flavourLengths);
// prints -> ["I love CHOCOLATE ice cream", "I love STRAWBERRY ice cream", ...etc]
Enter fullscreen mode Exit fullscreen mode

Single statement which includes return (e.g. the super-terse way)

Even better, if your statement is very short or the only statement is a return, then you can reduce your arrow function into the following:

console.log(flavours.map(flavour => flavour.length));
// prints -> [9, 10, 7, 6, 6]
Enter fullscreen mode Exit fullscreen mode

What about this?

this is a complex and often confusing topic in the land of JavaScript. From the MDN documentation on arrow functions:

Until arrow functions, every new function defined its own [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) value (based on how function was called, a new object in the case of a constructor, undefined in strict mode function calls, the base object if the function is called as an \object method, etc.).

Traditionally declared anonymous functions like to bind this to the global object, which can cause problems, both in execution and development.

Arrow functions help by providing a this that is taken from the local context. For example, if this isn't found in the current scope, it will be taken from the enclosing scope.

To illustrate just how this works, let's look at two examples:

A traditional function with global this scoping

function printLemurName() {
    console.log('nothing here but us globals');
}

const lemurLand = {
    lemurs: ['Dave', 'John', 'Alice', 'Tanya', 'Lemur No. 5'],
    printLemurName: function(lemur) {
        console.log('This lemur is called ' + lemur);
    },
    printAllLemurNames: function() {
        // Right now, `this` is bound to the lemurLand object, great! 
        this.lemurs.forEach(function(lemur) {
            // but here, `this` is bound to the global object...oh dear
            this.printLemurName(lemur);
        });
    },
};

lemurLand.printAllLemurNames();
// 'nothing here but us globals'
// 'nothing here but us globals'
// 'nothing here but us globals'
// 'nothing here but us globals'
// 'nothing here but us globals'
Enter fullscreen mode Exit fullscreen mode

The same example, replaced with an arrow function

//...same preceding code

    printAllLemurNames: function() { 
        this.lemurs.forEach(lemur => {
            // ahh that's better, `this` is correctly set to the lemurLand object
            this.printLemurName(lemur);
        });
    },
};

lemurLand.printAllLemurNames();
// 'This lemur is called Dave'
// ...etc.
// 'This lemur is called Lemur No. 5' 
Enter fullscreen mode Exit fullscreen mode

There's more to arrow functions

This is a quick intro guide into what arrow functions are, what role they play in clean, readable code writing and what problems they can solve with their helpful application of this.

However, they do have some other, advanced uses and I would highly recommend reading the MDN documentation for more examples, use cases and a more indepth technical overview of arrow functions.

Top comments (5)

Collapse
 
petedermott profile image
Pete Dermott

Good article, thanks!

Whilst I appreciate the changes to "this", I always find the syntax of arrow functions to be damn ugly and confusing. It just never feels verbose enough for a new javascript developer to know what is going on.

Collapse
 
kendalmintcode profile image
Rob Kendal {{☕}} • Edited

Haha, I'm the exact opposite, I love them! But they're like any tool, I think they have a purpose and a place depending on your approach. For me, they offer a great way to introduce more readable code, especially in smaller cases.

For example:

// this, is more readable, or certainly neater
const newArr = oldArr.map(item => item.thing);

// than this,
const newArr = oldArr.map(function(item) { 
 return item.thing; 
});

BUT...

I do agree wholeheartedly with you that terseness != readable all the time and yes, I would imagine less experienced devs (well, all devs really) could get lost with an abuse of over simplified and terse arrow functions littered all over the shop.

Collapse
 
straleb profile image
Strahinja Babić

Ohh cool a post bout Arrow functions, it's definitely a thing that new developers should be able to check out a great article, not a fan of them but still good to know :D

Collapse
 
kendalmintcode profile image
Rob Kendal {{☕}}

Thanks Strahinja, glad you liked it. They’re definitely cause a split in opinion but it’s good to get all sides ☺️

Collapse
 
technophile profile image
Vatsal Hirpara

Great post! I had been looking for explanation on how 'this' behaves inside arrow function.