DEV Community

Victoria Lo
Victoria Lo

Posted on • Originally published at lo-victoria.com on

A Simple Guide to Arrow Functions in JavaScript

In this article, we are tackling a highly familiar concept in JavaScript: Arrow Functions. I hope today's article will be useful for JavaScript beginners who are still learning about functions and arrow syntax. Without further ado, let's begin!

What is an Arrow Function?

If you are learning JavaScript, it is inevitable that you will hear about "arrows". This little syntax has been around since ES6 is introduced, and it revolutionizes the way we write JavaScript functions.

So, an arrow function basically uses the arrow syntax to accept arguments like a normal function and run in their enclosing scope context.

Syntax

Here's the basic arrow functions syntax:

//1. Function that returns a single expression
(param1, param2, ...) => return_expression

//2. Function that contains some lines of code
(param1, param2, ...) => {
   statements
   return some_expression
}

//3. Function with only one parameter
param => return_expression
param => {statements}

//4. Function with no parameter
() => return_expression
() => {statements}
Enter fullscreen mode Exit fullscreen mode

Example

Let's say you have a function expression such as:

const add = function (a, b){
    return a+b;
}
Enter fullscreen mode Exit fullscreen mode

The same function can be written as an arrow function like:

const add = (a,b) => a + b
Enter fullscreen mode Exit fullscreen mode

As observed in the example, arrow functions are good for 2 things:

  1. Concise and more readable code: no need to write 'function' in front and code looks more concise.
  2. Implicit return: no need to write 'return' for single return statements.

When to use them

Besides understanding how to write them, it is also important to know when to use them. An arrow syntax is useful to apply in the following types of functions:

1. Functions that iterate over and over again

Arrow functions can be very useful for functions that iterate over the items of some type of list such as an array or a string.
Common JavaScript methods such as map(), filter() and reduce() can look much cleaner with the help of arrow functions.

For example, we have a function that uses map() to add 1 to each element in the array. Here's what it looks like in a non-arrow function.

let numbers = [1, 2, 3, 4];

numbers.map(function(num) {
  return num+1;
});

//output array: [2,3,4,5]
Enter fullscreen mode Exit fullscreen mode

With the arrow function, it will be faster to write.

let numbers = [1, 2, 3, 4];

numbers.map(num => num+1);  //output array: [2,3,4,5]
Enter fullscreen mode Exit fullscreen mode

Now isn't that much simpler to write and easier to read?

2. Promise chains

It is easy for Promises to look very repetitive and lengthy when using non-arrow syntax. Take a look at this example:

this.fetchSomething()
.then(function(res){
     return res.json();
})
.then(function(json){
     return json.data;
})
.then(function(data){
     return data.map(function(items) {
        items.name;
     })
})
Enter fullscreen mode Exit fullscreen mode

This looks very repetitive and tedious to write with having to always write 'function' and 'return' in almost every single line. We can simplify this by using arrow functions instead:

this.fetchSomething()
.then(res => res.json())
.then(json => json.data)
.then(data => data.map(items => items.name));
Enter fullscreen mode Exit fullscreen mode

Look at that! The arrow functions do what its best at - keeping conciseness by reducing redundant words and implicit returning.

3. Callback Functions

This is probably what most beginners will use arrow functions for. Callback functions are very common in JavaScript and reducing them with the arrow syntax can drastically save a developer time and effort.

If you are unsure what callback functions are, read Conquering JavaScript Callback Functions.

Let's illustrate this with a simple example:

function myName(name, callback){
     console.log(`Hi, I am ${name}!`);
     callback();
}

//Call the function
myName("Victoria", function() {
     console.log("I am a web developer!");
})
/*
Output: 
Hi, I am Victoria! 
I am a web developer!
*/
Enter fullscreen mode Exit fullscreen mode

Replacing the callback with the arrow syntax, we get:

function myName(name, callback){
     console.log(`Hi, I am ${name}!`);
     callback();
}

myName("Victoria", () => console.log("I am a web developer!"));
/*
Output: 
Hi, I am Victoria! 
I am a web developer!
*/
Enter fullscreen mode Exit fullscreen mode

And there you go! These 3 types of functions are where arrow functions can be fully used and benefit from. Now let's look at where we cannot use them.

When NOT to use

So far we've discussed how great and useful the arrow syntax is. But now it's time to look at its limitations and in which context it will be a bad idea to use.

1. Constructors

Arrow functions do not create their own scope when executed. They are bound to their enclosing scope context, which means unlike regular functions, arrow functions do not have their own this.

Below is an example of a typical constructor using an arrow function. It throws an error when it is invoked with the 'new' keyword.

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

const roger = new Person('Roger');

//Output: TypeError Person is not a constructor

Enter fullscreen mode Exit fullscreen mode

On the other hand, using a regular function will work properly.

const Someone = function(name){
    this.name= name;
    console.log(this);
}
const james = new Someone('James');

//Output: Someone {name: 'James'}

Enter fullscreen mode Exit fullscreen mode

2. Object Methods

When we create an object method in JavaScript with a regular function, it creates its own scope so that this refers to the object that has the method stored as its property. However, arrow functions do not have their own scope so this would refer to the window object. This results in this being a window object and any of its property being undefined.

Let's demonstrate it with code:

var obj = { 
  i: 10,
  b: () => console.log(this.i, this), // does not create a new scope
  c: function() {
    console.log(this.i, this);
  }
}

obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}
Enter fullscreen mode Exit fullscreen mode

Code from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

As seen from the code above, method b which is created using the arrow function outputs an undefined value and a window object; whereas method c, constructed with a regular function outputs correctly.

3. Callback Functions with 'this'

The fact that arrow functions do not have their own scope and this also makes them unsuitable for callback functions which includes 'this'. Consider the following code:

const myButton = document.getElementById('example');
myButton.addEventListener('click', () => {
  console.log(this); //refers to window not the button itself
  this.innerHTML = 'Clicked'; //so this won't work
});
Enter fullscreen mode Exit fullscreen mode

The callback function intends to use this to refer to the button and set its innerHTML to 'Clicked'. However, this will not work because the arrow function will make this refer to the window object instead.

Conclusion

Arrow functions are a necessity in JavaScript programming. They provide a revolutionary way to reduce code repetition and improve readability in substitute of regular functions. They do, nevertheless, come with limitations which mainly stem from scope.

Just like learning any new concept, it is important to understand when it is best and when it is not best to use this type of function. I hope this article has given a few helpful insights. Please leave a like or share if it is helpful in any way. Thanks for reading and I encourage you to check out the 'Further Reading' section below for a more in-depth info on arrow functions.

Further Reading

Top comments (0)