Introduction
The 6th edition of ECMAScript, the official name of the JavaScript programming language, was finalized in 2015. This update adds significant new syntax for writing complex applications, including class declarations, let and const keywords, promises, template literals, iterators, generators, and arrow functions. The complete list of new features is extensive.
In this blog post, we’re going to focus on arrow functions.
Click to enlarge
Arrow functions
In JavaScript one typically declares a function like the following, with a function name, an optional list of parameters and a function body:
1 2 3 | function name( parameters ) { // function body } |
One can also create anonymous functions, omitting the function name, when assigning the function to a variable:
1 2 3 | var example = function( parameters ) { // function body } |
Starting with ES6, one can also write anonymous functions using arrow functions. See the following example.
1 2 3 | var example = ( parameters ) => { // function body } |
Unlike traditional functions, arrow functions:
Do not create their own scope
Cannot be named
Cannot be used as constructors
Do not have a prototype property
Static scope
Unlike traditional functions, an arrow function does not create its own scope. Instead, it is bound to its static scope. Specifically, all of these point to their containing scope:
Example 1
Consider the following code. We have a timer object with a seconds counter and a function named start. When the timer is started, we increment the seconds counter once per second. After a few seconds, we log the number of seconds that have elapsed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var timer = { "seconds": 0, "start": function() { setInterval( () => { this.seconds += 1; }, 1000 ); } }; timer.start(); setTimeout( function() { console.log( timer.seconds ); }, 3500 ); // <- 3 |
If we had defined the function passed to setInterval as a traditional function, this would have been bound to the function itself, which doesn’t have a seconds counter. The result follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var timer = { "seconds": 0, "start": function() { setInterval( function() { this.seconds += 1; }, 1000 ); } }; timer.start(); setTimeout( function() { console.log( timer.seconds ); }, 3500 ); // <- 0 |
Example 2
Consider the following code. We have a getLogger function that returns a function that will log the arguments passed to it. Since an arrow function does not create a scope of its own, the arguments object refers to the arguments passed to the getLogger function (“a”, “b”, “c”).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function getLogger() { return () => { console.log( arguments[ 0 ], arguments[ 1 ], arguments[ 2 ] ); } } const logger = getLogger( "a", "b", "c" ); logger( 1, 2, 3 ); // <- a b c |
If we had instead defined the arrow function as a traditional function, the arguments object would refer to the arguments passed to function returned by the getLogger function (1, 2, 3).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function getLogger() { return function() { console.log( arguments[ 0 ], arguments[ 1 ], arguments[ 2 ] ); } } const logger = getLogger( "a", "b", "c" ); logger( 1, 2, 3 ); // <- 1 2 3 |
Shorthands
Consider the following traditional JavaScript function:
1 2 3 | var triple = function( value ) { return value * 3; } |
Written as an arrow function, the function would look like this:
1 2 3 | var triple = ( value ) => { return value * 3; } |
If a function accepts exactly one parameter, one can omit the parentheses around the parameter:
1 2 3 | var triple = value => { return value * 3; } |
If a function contains just a return statement, one can omit the parentheses around the function body and the return keyword:
1 | var triple = value => value * 3; |
Use case
A common use case for arrow functions is when using a functional programming paradigm. For example:
1 2 3 4 5 6 7 8 | [ 1, 2, 3, 4, 5 ] .map( value => value * 3 ) .filter( value => value > 6 ) .forEach( value => console.log( value ) ); // <- 9 // <- 12 // <- 15 |
In our next blog post, we’ll take a look at class declarations in ES6.