Do Not Be Afraid of the Arrow Function

Ann Layman
5 min readDec 16, 2017

--

If you are not already using JavaScript ES6 arrow functions, my job is to convince you to start using that sleek syntax immediately. But first, before your attachment issues are triggered, don’t panic, we won’t say goodbye to regular functions- they still have their time and place. So let’s talk about the pros and the cons of using arrow functions.

Baby Steps.

Arrow functions are simply a more concise way to write function expressions. Fun fact, they are also called fat arrow functions because of the => which as you can see, looks like a fat arrow.

Let’s familiarize ourselves with the sexy syntax.

Here is the regular old function syntax you are familiar with. Remember, there are already two different ways in which we can write them:

//1 function declarationfunction product (a, b) {
return a * b;
}
//2 function expressionconst product = function (a, b) {
return a * b;
}

Now let’s turn this into an arrow function:

const product = (a, b) => {
return a * b;
}

But wait, you might be thinking, that’s not even a big improvement. A cool aspect of arrow functions is that they allow implicit returns. If your function is a one-line-function AKA has a concise body, you do not need to use the return keyword. The product function above could also be written like this:

const product = (a, b) => a * b

Furthermore, if your function only has one parameter, you do not need to include the parentheses around that parameter.

Let’s change the function slightly so that it only accepts one parameter.

// ES5
const double = function (a) {
return 2 * a;
}
// ES6
const double = a => 2 * a

Now that is beautiful.

With arrow functions you no longer have to type the keywordsfunction or even often return!

Besides being super succinct, the other huge benefit of arrow functions is that there is no binding of this. Instead, this retains its meaning based on its original context, we say it is bound lexically. The alternative would be to redefine the value of this within the function body. Side-note, if you are still confused about this , it can be a long learning process, even advanced developers continue to struggle with it.

Arrow functions make it easier to predict behavior of callback functions (functions given as parameters to other functions) and can help prevent some bugs within callbacks surrounding the value of this.

Let’s look at an example of a problem that might arise when we use a higher order function in an object method:

const arrayMultiplier = {
multiplier: 3,
multiply: function(array) {
console.log("Multiplying w/ multiplier: " + this.multiplier);
return array.map(function(value) {
return this.multiplier * value;
});
}
}
console.log(arrayMultiplier.multiply([1, 2, 3]));

Why doesn’t this work?

When we call the multiply method, it first logs a message that references this. No problem here since we’re inside a regular method. However, we will run into trouble inside the higher order map function. Inside the callback function, we reference this but since we are now in a new anonymous function, this refers to the global object. The workaround for this would be to either call bind on the callback function, or to set a variable equal to this before the call to map and reference that variable inside of the callback.

Luckily, arrow functions make it so that we can easily retain the outer this context. We can rewrite the above code to look like this:

const arrayMultiplier = {
multiplier: 3,
multiply: function(array) {
console.log("Multiplying w/ multiplier: " + this.multiplier);
return array.map(value => this.multiplier * value)
}
}
console.log(arrayMultiplier.multiply([1, 2, 3]));

Here, even though the right side of the fat arrow is technically a different function, this still refers to the arrayMultiplier object. Note that we still used a normal function to define the multiply method. To learn more about why, keep reading below.

Just be sure to watch out on a few things with arrow functions.

There were two main issues I ran into when I first starting converting all my functions to arrow functions.

  1. Do not use arrow functions when you want to use an arguments object.

arguments is a keyword that we can use in a function to access an Array-like value containing all the parameters that were passed into that function. You do not have the arguments object if you use an arrow function.

const numbers = () => {
let result = true;
[…arguments].forEach(element => {
if (typeof element !== “number”) {
result = false;
}
})
return result;
}

The above function aims to see if each parameter passed in is of the type “number”. Unfortunately this function would never achieve our intended output because the arguments are not available to us with an arrow function. We must re-write the above example like so:

const numbers = function() {
let result = true;
[...arguments].forEach(element => {
if (typeof element !== "number") {
result = false;
}
})
return result;
}

Notice we can still of course use an arrow function in our forEach method callback function.

If you haven’t had to use arguments before, check out this and other related CodeWars problems to get an idea for how arguments can be very useful, and make sure you don’t use arrow functions!

2. Do not use arrow functions when defining methods on objects

In JavaScript, instance methods are typically defined on the prototype of the constructor. These functions are named as such because any instance of that constructor class will then inherit that functionality.

Below we have an Article model, and we are attaching the method truncate to the prototype. We use the this keyword to refer to the Article instance being truncated. If we were to use an arrow function instead of a regular function expression, this would be undefined because it is not bound to the instance. It inherits its context from the parent scope which in this case is the global object. And since there is no key of content on the global object, its value returned is undefined.

Article.prototype.truncate = function(length) {
this.content = this.content.substring(0, length);
}

The first couple times you see arrow functions you might be thrown off. My biggest suggestions is to just go and start using them. Solve a few CodeWars problems, take the few seconds to stop and think about how to compose your arrow function, look up the syntax for a reminder and after just several annoying times of slowly writing them, you will quickly pick them up and be glad you did! Just don’t use arrow functions if you need arguments or if you’re writing an instance method!

--

--