1. javascript
  2. /es6
  3. /arrow-functions

Arrow Functions in ES6 JavaScript

Getting Started

JavaScript treats functions as first-order citizens, allowing us to pass them as arguments, assign them to variables, and return them from other functions.

With the arrival of ES6, we now have a shorthand syntax for writing anonymous functions, known as Arrow Functions recognizable by the "fat arrow notation" =>.

The feature allows us to write more compact code and simplify our syntax, making it easier to read, understand and modify.

Basic Syntax of Arrow Functions

Let's start with the basics. The syntax of arrow functions is quite simple and can be written in just one line:

const greet = (name) => `Hello, ${name}!`;
console.log(greet('John')); // Hello, John!

As you can see, the arrow function takes in a single argument name, and returns a string "Hello, ${name}!". In the traditional function syntax, this would look like this:

const greet = function(name) {
  return `Hello, ${name}!`;
};
console.log(greet('John')); // Hello, John!

Syntax Variants

Arrow functions can be written with or without parameters, and the parentheses can be omitted in certain cases. For example:

// with parameters
const add = (a, b) => a + b;

// without parameters
const sayHi = () => console.log("Hi!");

// without parentheses for a single parameter
const square = x => x * x;

Arrow functions can also be written in both multi-line and single-line variations. The implicit return works in single-line arrow functions, but for multi-line arrow functions, an explicit return statement must be used.

// multi-line
const sumSquared = (a, b) => {
  const sum = a + b;
  return sum * sum;
};

// single-line
const multiply = x => x * 2;

Multi-Line and Single-Line Variations

Arrow Functions can have either a single-line or multi-line body.

For single-line bodies, you can omit the curly braces {} and include the expression after the => symbol:

const square = num => num * num;
console.log(square(4)); // 16

For multi-line bodies, you need to include the curly braces {} and include the statements inside:

const multiply = n => n * 2;

console.log(multiply(5)); // Output: 10

The Return Value in Arrow Functions

In Arrow Functions, the return statement is implicit when the body of the function consists of a single expression. In such cases, you don't need to use the return keyword, and the expression itself will be returned by the function.

const square = (num) => num * num;
console.log(square(5)); // 25

However, if the function body contains multiple expressions or statements, we must include return:

Here's an example of an explicit return in an Arrow Function:

const squareRoot = (num) => {
  const result = Math.sqrt(num);
  return result;
};
console.log(squareRoot(9)); // 3

The Limits of Arrow Functions

Arrow functions, while powerful and concise, have some limitations that should be considered.

They don't have their own bindings to this, meaning that if we try to access these values inside an arrow function, we'll get the value from the nearest non-arrow function scope.

const person = {
  name: 'John Doe',
  hobbies: ['reading', 'traveling'],
  showHobbies: function() {
    this.hobbies.forEach((hobby) => {
      console.log(`${this.name} loves ${hobby}`);
    });
  }
};
person.showHobbies();
// Output:
// John Doe loves reading
// John Doe loves traveling

Another thing to keep in mind is that arrow functions shouldn't be used as methods or constructors. Calling them with new throws a TypeError. They also don't have access to the new.target keyword.

const Person = (name) => {
  this.name = name;
};
const john = new Person('John Doe');
// Uncaught TypeError: Person is not a constructor

Final Thoughts

Arrow Functions are a compact and convenient way to write functions, and they have become a staple of modern JavaScript development. They have a clear and concise syntax that makes code more readable and easier to maintain. However, we should understand their limitations and when to use them appropriately.

While Arrow Functions are perfect for small, self-contained tasks, they shouldn't be used for everything. Regular functions are still the go-to choice for many use cases, especially when dealing with certain bindings.

Useful Resources

The Official ECMAScript 2015 Language Specification

Check out other useful features in our ES6 JavaScript guide.