Arrow functions in ECMAScript 6 (ES6)

Hi All,

You will find some of the new features introduce in ES 6 in my previous post. Now let’s get more details on Arrow functions in ECMAScript 6.

The ECMAScript 6 arrow function syntax is a shorthand for the ECMAScript 5 function syntax. It supports both block and expression bodies. The value of this inside the function is not altered: it is the same as the value of this outside the function. No more var self = this to keep track of the current scope.

Here’s how the syntax looks like if we have a single argument and just want to return the results for an expression.

[1, 2, 3].map(num => num * 2) // <- [2, 4, 6]

/* ES5 equivalent */
[1, 2, 3].map(function (num) { return num * 2 }) // <- [2, 4, 6]

If we need to declare more arguments (or no arguments), we’ll have to use parenthesis.

[1, 2, 3, 4].map((num, index) => num * 2 + index) // <- [2, 5, 8, 11]

You might want to have some other statements and not just an expression to return. In this case you’ll have to use bracket notation.

[1, 2, 3, 4].map(num => {
  var multiplier = 2 + num
  return num * multiplier
}) // <- [3, 8, 15, 24]

If we need to return an object literal, we’ll have to wrap the expression in parenthesis. That way the object literal won’t be interpreted as a statement block (which would result in a silent error or worse, a syntax error because number: n isn’t a valid expression in the example below. The first example interprets number as a label and then figures out we have an n expression. Since we’re in a block and not returning anything, the mapped values will be undefined. In the second case, after the label and the n expression, , something: ‘else’ makes no sense to the compiler, and a SyntaxError is thrown.

[1, 2, 3].map(n => { number: n })
// [undefined, undefined, undefined]

[1, 2, 3].map(n => { number: n, something: 'else' })
// <- SyntaxError

[1, 2, 3].map(n => ({ number: n }))
// <- [{ number: 1 }, { number: 2 }, { number: 3 }]

[1, 2, 3].map(n => ({ number: n, something: 'else' }))
/* <- [
  { number: 1, something: 'else' },
  { number: 2, something: 'else' },
  { number: 3, something: 'else' }]
*/

A cool aspect of arrow functions in ES6 is that they’re bound to their lexical scope.

function Timer () {
  this.seconds = 0
  setInterval(() => this.seconds++, 1000)
}
var timer = new Timer()
setTimeout(() => console.log(timer.seconds), 3100)
// <- 3

Keep in mind that the lexical this binding in ES6 arrow functions means that .call and .apply won’t be able to change the context. That means invoking an arrow function through the call() or apply() methods can only pass in arguments, but has no effect on this:

var adder = {
  base : 1,
    
  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };
            
    return f.call(b, a);
  }
};

console.log(adder.add(1));         // This would log to 2
console.log(adder.addThruCall(1)); // This would log to 2 still

I think arrow functions are particularly useful in most functional programming situations such as when using .map, .filter, or .reduce on collections. Similarly, arrow functions will be really useful in asynchronous flows since those typically have a bunch of callbacks that just do argument balancing, a situation where arrow functions really shine. Please share your thoughts on arrow functions in comments.

Advertisements

One thought on “Arrow functions in ECMAScript 6 (ES6)

  1. Pingback: What’s new in ECMAScript 6 (ES6) | UIthought - Web Development Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s