My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
Using JavaScript Arrow Functions

Using JavaScript Arrow Functions

Chuks Festus's photo
Chuks Festus
·Mar 20, 2017

Classical JavaScript function syntax doesn’t provide for any flexibility, be that a 1 statement function or an unfortunate multi-page function. Every time you need a function you have to type out the dreaded function () {}. To me it was a serious pain especially after working with coffeescript. But thank God!! the maintainers of Javascript decided to save the day and gave us the fat arrow

Arrow functions also called “fat arrow” functions are a more concise syntax for writing function expressions. They utilize a new token, =>, that looks like a fat arrow. Arrow functions are anonymous and change the way this binds in functions.

By using arrow function we avoid having to type the function keyword, return keyword (it’s implicit in arrow functions), and curly brackets.

Using Arrow Functions

Two factors influenced the introduction of arrow functions: shorter functions and non-binding of this.

Shorter functions

Let’s compare how ES5 code with function expressions can now be written in ES6 using arrow functions.

//ES5
add = function(x, y) {
    return x + y;
}
console.log(add(1,2)); // prints 3
//ES6
add = (x,y) =>  x + y
console.log(add(1,2));  // prints 3

Cool huh? The arrow function example above allows a developer to accomplish the same result with fewer lines of code and approximately half of the typing. The syntax for arrow functions comes in many flavors depending upon what you are trying to accomplish, that is both the arguments and the body can take different forms depending on usage. For example, the following arrow function takes a single argument and simply returns it:

// ES6:
let arrowFunc = value => value;
// ES5:

var reflect = function(value) {
    return value;
};

When there is only one argument for an arrow function, that one argument can be used directly without any further syntax. Similarly, a function without any named arguments must use empty parentheses to start the arrow function declaration:

// ES6:
let add = () => 1 + 2;

// ES5:

let add = function() {
    return 1 + 2;
};

Non-binding of this

Until arrow functions, every new function defined its own this value, This proved to be annoying with an object-oriented style of programming. Since the value of this can change inside of a single function depending on the context in which it’s called, it’s possible to mistakenly affect one object when you meant to affect another. Consider this example:

function Person() {
  // The Person() constructor defines `this` as an instance of itself.
  this.age = 0;

  setInterval(function growUp() {
   /* In non-strict mode, the growUp() function defines `this` 
       as the global object, which is different from the `this`
       defined by the Person() constructor.*/
   this.age++;
  }, 1000);
}

let p = new Person();

An arrow function does not create its own this context, so this has its original meaning from the enclosing context. Thus, the following code works as expected:

function Person(){
  this.age = 0;
 setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}
let p = new Person();

Pitfalls of Arrow Functions

The new arrow functions bring a helpful function syntax to ECMAScript, but as with any new feature, they come with their own pitfalls and gotchas. Here are a couple things you need to watch out for when using arrow functions.

More about this

Since this is not bound in arrow functions, the methods call() or apply() can only pass in parameters. this is ignored. The value of this inside of a function simply can’t be changed–it will be the same value as when the function was called. If you need to bind to a different value, you’ll need to use a function expression.

No binding of arguments

Arrow functions do not bind an arguments object. Thus, in this example, arguments is simply a reference to the same name in the enclosing scope:

let arguments = 42;
let arr = () => arguments;

arr(); // 42

function foo() {
  let f = (i) => arguments[0] + i; // foo's implicit arguments binding
  return f(2);
}

foo(1); // 3

However using rest parameters is a good alternative to using an arguments object.

function foo() { 
  let f = (...args) => args[0]; 
  return f(2); 
}

foo(1); // 2

Constructors

Arrow functions cannot be used as constructors as other functions can. Don’t use them to create similar objects as you would with other functions. If you attempt to use new with an arrow function, it will throw an error. Arrow functions, like built-in functions (aka methods), don’t have a prototype property or other internal methods. Because constructors are generally used to create classlike objects in JavaScript, you should use the new ES6 classes instead.

Conclusion

Arrow functions are an interesting new feature in ECMAScript 6, and one of the features that is pretty solidified at this point in time. As passing functions as arguments has become more popular, having a concise syntax for defining these functions is a welcome change to the way we’ve been doing this forever. The lexical this binding solves a major painpoint for developers and has the added bonus of improving performance through JavaScript engine optimizations.