Skip to content

Instantly share code, notes, and snippets.

@jefflau
Last active December 22, 2016 16:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jefflau/90ecf88a2818f52cae49 to your computer and use it in GitHub Desktop.
Save jefflau/90ecf88a2818f52cae49 to your computer and use it in GitHub Desktop.
A journey through ES6 - Part 2

#Arrow Functions

Arrow functions (also known as fat arrow functions) are awesome. They do two main things for you. Create a shorter syntax, and lexically scope this.

##Shorter syntax

//ES5
[1, 2, 3].map(function(n){ return n + 1 } // [2, 3, 4]
//ES6
[1, 2, 3].map(n => n + 1) // [2, 3, 4]

Heres a few rules for this shorter syntax

  • The parentheses are optional for a single argument (unless you're using ES6 features rest, destructuring). A function with no argument still needs the parentheses
  • If the function is just a single line express you can omit the return statement and omit the {} surrounding the function block
  • If your single line expression returns an object, you must wrap it with () so it'll look like: ({a: 1, b: 2})

Check this awesome diagram by @getify for further clarification

When to use Arrow functions

If your function isn't so simple we'll have to do this:

//ES5
[1, 2, 3].reduce(function(acc, cur) {
  var sum = acc + cur 
  return sum;
}
//ES6
[1, 2, 3].reduce((acc, cur) => {
  var sum = acc + cur // you could do this on the last line and not use a return, 
                      // but if you did a lot of manipulation
                      // and wanted to split it over multiple expressions
                      // you'd have to explicitly return
  return sum;
}

###Implicit return with object literals

//object needs the wrapping parentheses if you're returning it without the return statement
[1, 2, 3].map(element => 
  ({
    id: element
  })
) // [{id: 1}, {id: 2}, {id: 3}]

##Lexically scoping this

With Javascript now we have some annoying issues with callbacks and the binding of this. The classic cases is when we pass an eventHandler a callback, but the this object is not bound to what we want. This means we need to use the .bind() method on the Function.prototype object or we have to bind this lexically to a variable such as var self = this.

With Arrow functions in ES6, arrow functions do not automatically gain their own this, they simply get it lexically from their enclosing scope and therefore alleviate this problem when we pass our callback to a function that assigns our this to something else.

###ES5 Problem

//ES5 problem
var component = {
  makeStuffFly = function() {
    //do some stuff
  }
  bindEvents = function() {
    var button = documentGetElementById('button');

    button.addEventListener('click', function(event){
      this.makeStuffFly() //
    })
  }
}

obj.bindEvents();

###ES5 Solution 1

var component = {
  makeStuffFly = function() {
    console.log('flying')
  }
  bindEvents = function() {
    var button = documentGetElementById('button')
    var self = this;

    button.addEventListener('click', function(event) {
      self.makeStuffFly()
    })
  }
}

component.bindEvents();

###ES5 Solution 2

//ES5 solution 2
var component = {
  makeStuffFly: function() {
    console.log('flying')
  },
  handleEvent: function(event) {
    this.makeStuffFly()
  },
  bindEvents: function() {
    var button = document.getElementById('button');

    button.addEventListener('click', this.handleEvent.bind(this)
    );
  }
}

component.bindEvents()

###ES6 Solution

//ES6 solution
var component = {
  makeStuffFly = function() {
    console.log('flying')
  }
  bindEvents = function() {
    var button = documentGetElementById('button');

    button.addEventListener('click', event => {
      this.makeStuffFly()
    })
  }
}

component.bindEvents();

As you can see the ES6 solution is a lot cleaner and saves you thinking about hard binding this using bind or littering your code with unnecessary var that = this or var self = this

##A couple caveats

  • Arrow functions do not have their own arguments variable like normal functions, but if you're using ES6 you can use rest parameter or default values
  • Arrow functions are always anonymous and therefore cannot be called recursively from inside itself. So you can't do recursion

Further reading and references

https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20&%20beyond/fig1.png https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment