R
P

Create digital products with unique idea

See all articels

ES6 - arrow function

Learn how to use arrow function

Rafal Pisarczyk posted on Nov, 2016

In this post we are going to explore one of the most interesting and most popular ES6 feature and you have probably seen them around, they look like (x)=> x + 1. Generally it is a new shorter syntax for defining function in javascript.

Arrow Function (also called fat arrow) - shorter function syntax

Arrow functions make our code more concise, and simplify.

Defining arrow function is easy and basic syntax is:

(param1, param2, param3) => expression

Example code behind shows how to make the same function in old (ES5 way) and using fat arrow:

es5-way

//ES5
var multiply1 = function (x1, x2) {
  return x1 * x2;
};

//ES6 (using arrow function)
var multiply2 = (x1, x2) => x1 * x2;

The next example will show you how to better use the arrow function in everyday coding:

var cars = [
  { class: 'hatchback', year: 2014, brand: 'fiat' },
  { class: 'van', year: 2010, brand: 'volvo' },
  { class: 'lmuzine', year: 2009, brand: 'bmw' },
  { class: 'hatchback', year: 2015, brand: 'renault' },
  { class: 'hatchback', year: 2008, brand: 'kia' },
];
//es5 (old way)
let filter = cars
  .filter(function (car) {
    return car.class == 'hatchback'; //looking for hatchback
  })
  .filter(function (car) {
    //not older than 2010
    return car.year > 2010;
  })
  .map(function (car) {
    //return only the brand
    return car.brand;
  });

The output:

['fiat', 'renault'];

arrow

Let's do this with arrow. We can removing function keyword and add fat arrow => to statement:

let filter = cars
  .filter((car) => {
    return car.class == 'hatchback'; //looking for hatchback
  })
  .filter((car) => {
    //not older than 2010
    return car.year > 2010;
  })
  .map((car) => {
    //return only the brand
    return car.brand;
  });

The result is of course the same. But we can do this better. If your code is one statement like 'return car.class == 'hatchback' we can make return statement implicitly.

Try in JSBin

let filter = cars
  .filter((car) => car.class == 'hatchback')
  .filter((car) => car.year > 2010)
  .map((car) => car.brand);

When there is only one argument for an arrow function you don't need to add parentheses around those arguments. If you are passing more than one arguments then the parentheses must be include.

But every medal has two sides. When not to use arrow function.

Arrow function is bound to scope where it's created.

var fun = () => {
  console.log(this === window);
};
fun(); // true

It's global window in this case. Lets' try another example using object literals:

var obj = {
  table: [1, 2, 3],
  method: () => {
    return this.table.filter((m) => m == 1);
  },
};
console.log(obj.method());
//TypeError: Cannot read property 'filter' of undefined

obj.method() throws TypeError because this.table is evaluated to undefined. Executing this.table inside method function is same as executing window.table which is undefined.

The same situation when defining methods on prototype object:

function Test(name) {
  this.name = name;
}
Test.prototype.getName = () => {
  console.log(this === window); // => true
  return this.name;
};
var obj1 = new Test('Rafal');
console.log(obj1.getName()); // => undefined

Instead of using shorter syntax method in this cases you should stay with old function syntax expression:

function Test(name) {
  this.name = name;
}
Test.prototype.getName = function () {
  return this.name;
};
var obj1 = new Test('Rafal');
console.log(obj1.getName()); // => Rafal

Conclusion

One of the most obvious benefits of using arrow function is shorter and less verbose syntax. To my opinion, besides the short and more concise syntax, its most significant benefit is to provide a better solution regarding this scope binding