ECMAScript 6 Arrow Functions

Arrow functions, also sometimes called “fat arrow” functions, are a new ES6 syntax for writing anonymous function expressions. We have looked at working with ES6 in previous entries about classes and module loading. (a.k.a the “next version of JavaScript”). A function expression in JavaScript refers to the notation where a developer sets a variable equal to a function like so…

var sum = function (a, b) { return a + b; }

Note that a function expression is different from a function declaration which would look like the following…

function sum(a, b) { return a + b }

So arrow functions are primarily centered around function expressions. They have 2 main purposes. For one, they provide a more concise syntax which is a nice thing to have and can make code more readable. If were to take our function expression above and rewrite it as an arrow function, it would look like the following…

var sum = (a, b) => a + b; 

As can be seen here, this syntax looks a bit different from our original function expression. We have the arrow pointer pointing a statement that has omitted the { } from encapsulating the function body and we have omitted the “return” statement. In the above arrow function these things are implied. If we wanted to we could include these things and the meaning of the function would be the same.

var sum = (a, b) => { return a + b };

There are few rules around the syntax of arrow functions to watch out for. If there is only one argument in an arrow function the parenthesis do not need to be included. So an arrow function that simply returns “a” could be written like so…

var getVal = a => a;

However if the arrow function takes no arguments, parentheses must be used…

var getVal = () => "Hello world!";

Another interesting case of arrow function syntax is returning an empty object. The following results in an error…

var getVal = () => { };

The compiler sees this as having nothing in the function body and does not know what to return. As a result when returning an empty object you have to do the following…

var getVal = () => ({ });

So as we can see, arrow functions give us a much more terse way of writing code, allowing for a more readable concise syntax. This becomes useful in cases when using functions that have callbacks involved as arguments. Many functions that that perform asynchronous operations with data have this format. The following asynchronous promise style function…

getData().then(function (data) {
    return data;
});

Could be rewritten as the following using arrow functions…

getData().then(data => data);

It is pretty apparent that the second example is a lot more compact. As the number of functions like these get chained together, it can make the code a lot easier to read once you get used to the syntax.

Another and perhaps a more important aspect arrow functions is that they handle the scope of the “this” pointer within the function in a different manner. In other words, in arrow functions “this” points to the scope of the parent environment that the arrow function is contained within. This is a very important distinction. Arrow functions do not create their own “this” as normal functions do. A side-effect of this is that you cannot instantiate an arrow function with the “new” keyword as you can with normal functions because arrow functions have no internal prototype property.

Why were things done this way in ES6 and why is this useful? This can be very useful because you now no longer have to use apply, call, or bind to bind to the parent scope. One of the more common uses of the bind method within JavaScript applications is to pass the parent scope downward as you go multiple levels deep within methods within in object literal. For example, let’s say we had the following very general “actionClass” object literal. A lot of JavaScript applications use this pattern as an implementation…

<div class="button">Click me!</div>

<script type="javascript">
    var actionClass = {

        init: function(){
            this.setEvents();
        },
        setEvents: function(){
            // we will set events here...

        },
        doSomething: function(){
            console.log('We are doing something');
        },

        doSomethingElse: function() {
            console.log('We are doing something else');
        }

    };

    actionClass.init();

</script>

As we can see we are calling the actionClass.init() method which will set up some event handlers. So let’s add an event (using jQuery) where when we click an element we call another one of the methods within our actionClass object.

<div class="button">Click me!</div>

<script type="javascript">
    var actionClass = {

        init: function(){
            this.setEvents();
        },
        setEvents: function(){

            jQuery('.button').on('click', function(){
                this.doSomething();
            });

        },
        doSomething: function(){
            console.log('We are doing something');
        },

        doSomethingElse: function() {
            console.log('We are doing something else');
        }

    };

    actionClass.init();

</script>

This code does not work. When we try to click the div we get an error in our console…

Uncaught TypeError: this.doSomething is not a function

Why is that? Well it is because the callback function for the click event has its own scope. “this” is now pointing at the function it is being called from. One way that developers solve this is by setting a variable to the parent scope. The following code works…

<div class="button">Click me!</div>

<script type="javascript">
    var actionClass = {

        init: function(){
            this.setEvents();
        },
        setEvents: function(){

            var self = this;

            jQuery('.button').on('click', function(){
                self.doSomething();
            });

        },
        doSomething: function(){
            console.log('We are doing something');
        },

        doSomethingElse: function() {
            console.log('We are doing something else');
        }

    };

    actionClass.init();

</script>

This is certainly a viable option and works fine for our simple example. However, as we go deeper and get more complex into multiple levels of nested functions with events or getting data asynchronously via AJAX requests or any number of other possibilities the process of constantly assigning variables to the scope that you want can get kind of messy. So what other approach can we take? This is where bind comes into the picture. We could also do something like the following…

<div class="button">Click me!</div>

<script type="javascript">
    var actionClass = {

        init: function(){
            this.setEvents();
        },
        setEvents: function(){

            jQuery('.button').on('click', function(){
                this.doSomething();
            }.bind(this));

        },
        doSomething: function(){
            console.log('We are doing something');
        },

        doSomethingElse: function() {
            console.log('We are doing something else');
        }

    };

    actionClass.init();

</script>

Simply by attaching .bind(this) after our function closing bracket } we are changing the scope of the function. We longer need to say var self = this;

But with arrow functions we can accomplish the same thing without having to resort to using “bind.” We can rewrite the above in the following manner (assuming we had ES6 compatibility in the browser or we transpiled the code)…

<div class="button">Click me!</div>

<script type="javascript">
    var actionClass = {

        init: function(){
            this.setEvents();
        },
        setEvents: function(){

            jQuery('.button').on('click', () => {
                this.doSomething();
            });

        },
        doSomething: function(){
            console.log('We are doing something');
        },

        doSomethingElse: function() {
            console.log('We are doing something else');
        }

    };

    actionClass.init();

</script>

Now because we have used an arrow function, the “this” pointer is set to the parent scope because of how arrow functions bind the lexical “this” to the parent. It may take a bit of getting used to but overall the differing scope of the “this” pointer combined with the concise syntax can make code that makes use of arrow functions a lot more readable and maintainable. We will be making use of them to some degree in upcoming examples, so it was necessary to at least introduce what arrow functions are and what they do.

This is just a brief look at a couple of the newer features found in ES6. Hopefully you found it helpful.

, , 9bit Studios E-Books

Like this post? How about a share?

Stay Updated with the 9bit Studios Newsletter

0 Responses to ECMAScript 6 Arrow Functions

    Leave a Reply

    Your email address will not be published. Required fields are marked *