Everything You Need To Know About JavaScript Arrow Functions

Write clear and concise code using ES6 arrow functions

Yogesh Chavan
Jan 10 · 5 min read
Photo by Luca Bravo on Unsplash

ES6 added a new syntax for writing functions which is getting heavily used in today’s JavaScript world.

Before ES6, there were two main ways of declaring functions.

1. Function Declaration Syntax:

function add(a, b) {
return a + b;
}

2. Function Expression Syntax:

const add = function(a, b) {
return a + b;
};

The first difference between normal function and arrow function is the syntax of writing function.

Using arrow function syntax, we can write the above add function as

const add = (a, b) => {
return a + b;
};

You might not see much difference here, apart from the arrow but if we have only one statement in the function body we can simplify the above arrow function as

const add = (a, b) => a + b;

Here we are implicitly returning the result of a + b, so there is no need of return keyword if there is a single statement.
So using arrow functions will make your code much shorter.

What if we want to return object from arrow function? how can we write it in single statement ?

When we add statement inside the curly brackets, it’s considered as start of function body like

const add = (a, b) => {
return a + b;
};

So to return an object from arrow function, we need to wrap in round brackets.

const getObject = () => { 
return {
name: 'Dan',
age: 30
};
};

The above code is equivalent to the following code

const getObject = () => ({ name: 'Dan', age: 30 });

If you are React developer, then this syntax is very useful while changing the state value.
Checkout my previous article regarding it HERE

If there is only one parameter to the function then we can also skip the brackets

const add = (a) => a + 5;

is same as

const add = a => a + 5;

But if there is no parameter to the function, adding brackets is necessary.

const add = () => 20 + 50;

The other difference between normal function and arrow function is arguments object. All the values passed to the function can be accessed using arguments object.

function add() {
let sum = 0;
for(let i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
console.log(sum);
}

add(1,2,3,4,5); // 15

but the arguments object is not available in arrow function.

const add = () => {
let sum = 0;
for(let i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
console.log(sum);
};

add(1,2,3,4,5); // Error: arguments is not defined

So if you are using arguments object to access the values passed to the function, you need to use the old syntax of writing function instead of arrow function.

The main difference between normal function and arrow function is regarding the this keyword.

this context is no longer bound in arrow function. Arrow functions use the context of where the function is defined as the this context.

Take a look at below code

const display = () => {
console.log(this);
}

display(); // it will print window object

If you execute this code in browser you will see that this points to window object. Take a look at below code

const countries = {
names: ["US", "INDIA", "JAPAN"],
display: function() {
console.log(this);
}
};

countries.display(); // it will print countries object

In this case, this inside display function will refer to countries object itself and not the window object.

Can you predict value of this in below code?

const countries = {
names: ["US", "INDIA", "JAPAN"],
display: function() {
setTimeout(function() {
console.log(this);
}, 1000);
}
};

countries.display();

It will print window object and not the countries object.
We can fix this using three ways.

  1. By Binding context of this to setTimeout callback function
const countries = {
names: ["US", "INDIA", "JAPAN"],
display: function() {
setTimeout(function() {
console.log(this);
}.bind(this), 1000);
}
};

2. By assigning the context of display function to local variable and use it inside setTimeout function

const countries = {
names: ["US", "INDIA", "JAPAN"],
display: function() {
const self = this;
setTimeout(function() {
console.log(self);
}.bind(this), 1000);
}
};

3. Third and the most preferred way is to convert the setTimeout callback function to arrow function

const countries = {
names: ["US", "INDIA", "JAPAN"],
display: function() {
setTimeout(() => {
console.log(this);
}, 1000);
}
};

Because arrow function does not have it’s own this context, it takes context from where the function is defined which is the countries object.

So now, we can easily print all the countries in setTimeout function using arrow function instead of using self or bind method

const countries = {
names: ["US", "INDIA", "JAPAN"],
display: function() {
setTimeout(() => {
this.names.forEach(country => console.log(country));
}, 1000);
}
};

Take a look at below code

// html 
<input id="btn" type="button" value="Click Me" class="btn" />

Here, we have provided normal function for the event handler so this will point to the button which we clicked.

// html 
<input id="btn" type="button" value="Click Me" class="btn" />

Here we have provided the arrow function for the event handler so in this case, this will not point to the button but instead the window object which is the context in which the function is defined.

So the point to remember is that, if you want to retain the this context, you need to use arrow function otherwise use normal function.

Take a look at below code

const greeting = function(message) {
return function(name) {
console.log(message + " " + name);
}
};

const hello = greeting('Hello');
console.log(hello('Adam')); // Hello Adam

const hi = greeting('Hi');
console.log(hi('Danny')); // Hi Danny
console.log(hi('Mike')); // Hi Mike

Here we have a greeting function which returns a function.
We can use arrow function to simplify it as

const greeting = message => name => {
console.log(message + " " + name);
};

const hello = greeting('Hello');
console.log(hello('Adam')); // Hello Adam

const hi = greeting('Hi');
console.log(hi('Danny')); // Hi Danny
console.log(hi('Mike')); // Hi Mike

So

const greeting = function(message) {
return function(name) {
console.log(message + " " + name);
}
};

is equivalent to

const greeting = message => name => {
console.log(message + " " + name);
};

Also, we can further simplify it in single line as

const greeting = message => name => console.log(message + " " + name);

To understand why this is useful, checkout my previous article HERE

Summary:

There are 3 main differences between normal function and arrow function
1. Syntax of writing function
2. Arguments object not available in arrow function
3. Difference with respect to how this works

That’s it for today. Hope you learned something new today.

Want to become an expert in Javascript? Download your free copy HERE

JavaScript in Plain English

Learn the web's most important programming language.

Yogesh Chavan

Written by

Full Stack Developer | Javascript | React | Nodejs. Subscribe to get weekly updates directly in your inbox https://subscribe-user.herokuapp.com/

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade