Everything you wanted and didn’t want to know about arrow functions in JavaScript

Susanna Kosonen
4 min readAug 9, 2018

Here’s how arrow functions came to be, and why you should embrace them sooner rather than later. This blog assumes you already know what arrow functions are, but haven’t started using them all over the place yet.

“yellow Awesome-printed signage” by Jon Tyson on Unsplash

ES6 standardised the Arrow functions into JavaScript

Arrow functions were introduced in the 6th Edition of the ECMAScript standard (ES6), which was released in 2015. In a developer survey that very same year, arrow functions were already reported as one of the most used features of ES6!

(Here’s a side note, in case you’re curious about what ECMAScript refers to. ECMAScript is the standard on which JavaScript build on. JavaScript is currently the most popular implementation of ECMAScript, although not the only one. ECMA is the “European association for standardizing information and communication systems”. The abbreviation comes from its old name, European Computer Manufacturers Association. They’re located in Geneva, Switzerland.)

Back to arrow functions. Who can we thank for bringing them to JavaScript? Turns out it’s this person called Jason Orendorff, who kindly identifies himself in an excellent in-depth blog about JS arrow functions.

ES6 arrow functions were implemented in Firefox by me, back in 2013. Jan de Mooij made them fast. Thanks to Tooru Fujisawa and ziyunfei for patches.

Arrow functions in Callback functions

Event handlers most often involve callback functions, eg. passing a function into another function as an object. Arrow functions make great one-liner, short functions. Implicit return, which means that you don’t have to explicitly type out “return”, makes arrow functions even easier on the eyes.

Consider functions as event handlers — you want to pass the function object, not invoke it. You also want to pass some parameters. Unfortunately you cannot do this:

myElement.addEventListener("click", someFunction(parameters)) 
// this will invoke the function, not pass the function as an //object!

Arrow functions will solve this by providing an easy wrap.

myElement.addEventListener("click", () => someFunction(parameters))
//you're passing it a function within a function, thus avoiding //invoking your original function while passing parameters

Arrow functions in binding this to the enclosing value

Arrow functions were introduced to also fix the this problem: Sometimes you want the function to hold on to the this it had upon definition (the enclosing scope), not grab a new this from where you’re invoking the function. Non-arrow functions always get a this from the surrounding execution context, whether you want it or not. This is not ideal in event handlers, setTimeouts or setIntervals, where you define the function at first, but want to invoke it later, in another context.

Consider this case of two employee objects, both of which will start getting a raise every second from the moment they’re created. NormalEmployee object will not have a working getRaise function, as it has a this that refers to the callback function, not the employee object! Meanwhile, our arrow function will work.

It’s good to keep in mind that arrow functions do not have their own this at all. More about that at the end of this blog.

This all combined: React

Arrow functions come very handy in React, where the bound this and short syntax are put to good use. In React, when you want to pass information from child component to its parent, you use callback functions. These callback functions are passed as props to the child and invoked in the child component, but may need to change the state of the parent component. The following handleClick will correctly toggle the state of the parent component, even though it is passed on as props to another context, a child component!

class ParentComponent extends React.Component {
constructor() {
super()
this.state = { clicked: false }
}
handleClick = () => {
const newValue = !this.state.clicked
this.setState({ clicked: newValue });
}

render() {
return (
<ChildComponent onClick={this.handleClick} text="Click me!"/>
);
}
}

Remember: if you want to pass arguments to your handleClick callback function, you can always wrap it in another arrow function inside the curly braces!

<ChildComponent onClick={() => this.handleClick(argument1, argument2)} text="Click me!"/>

Quick warnings about when not to use arrow functions

There are some use cases where you’re better off without arrow functions. You cannot use them as constructors, due to their dependency on the declarative context (surrounding scope). Can’t call new, or super(). Arrow functions might not be very useful as object methods either, since you want the function to receive this from the new surrounding context!

Use non-arrow functions for methods that will be called using the object.method() syntax. Those are the functions that will receive a meaningful this value from their caller.

Also, be careful with curly braces in your arrow functions. Can you tell the difference between this object literal {} and this code block {}? Well, neither can the JavaScript engine! If you want to use object literal inside your arrow function, you have to wrap it in a parenthesis. Otherwise it will be interpreted as an expression and will error out.

const newPersonnel = oldPersonnel.map(employee => {//some new employee obj}) //will not work!const newPersonnel2 = oldPersonnel.map(employee => ({//some new employee obj})) //will work!

By using methods and arrow functions for everything else, you may avoid having to type the word “function” 99% of your coding time!

That other JS arrow function you didn’t know about

I was very surprised to find out that the arrow function isn’t actually the only arrow function around in JavaScript. Take a look at this pretty loop!

let x = 5
while(x-->0) {console.log(“countdown”, x)}
/////this will work and produce the following logs
//LOG:countdown 4
//LOG:countdown 3
//LOG:countdown 2
//LOG:countdown 1
//LOG:countdown 0

How does it work? Magic!*

*It’s just the same thing as writing while( (x--) > 0) { //do something } .

--

--

Susanna Kosonen

A journalist-turned-web-developer writes about her coding bugs and wins alike.