Introduction to JavaScript Arrow Functions

Arrow functions, introduced in ES6/ECMAScript 2015, are a syntactically compact alternative to regular ES5 functions. They are undoubtedly one of the most loved features of ES6 and are widely used nowadays. Arrow functions introduced a new way to write concise functions.

Here is a function written in ES5 function syntax:

function absolute(num) {
  return Math.abs(num)
}

absolute(-9) //9

Now, here is the same function written using ES6 arrow function syntax:

const absolute = num => {
  return Math.abs(num)
}

absolute(-9) //9

If the function body contains just a single statement, we can even omit the brackets and write everything in one line:

const absolute = (num) => Math.abs(num)

Function Parameters

If there are no parameters, just add empty parentheses before =>:

const pi = () => Math.PI

You can even replace empty parentheses with _:

const pi = _ => Math.PI

If you have one or more parameters, just pass them in the parentheses:

const abs = (num) => Math.abs(num) // on parameter
const sum = (a, b) => a + b    // two parameters

For just one parameter, you can remove the parentheses:

const abs = num => Math.abs(num)

Concise vs. Block Body

An arrow function can have either a concise body or the block body. If the function contains just one statement, use the concise body. In a concise body, only the expression is specified that implicitly returns a value (without using the return keyword):

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

In a block body, you must use an explicit return statement:

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

Look at the curly braces. They are required in a block body to wrap statements:

const oddNumber = num => {
  if (num % 2 == 0) {
    return false
  } else {
    return true
  }
}

Object Literals

If you are returning an object literal using the concise body, it must be wrapped in parentheses to avoid it being treated as a block body:

const json = () => ({ x: 2 })

this Keyword

In regular function expressions, the this keyword is bound to a different value based on the context in which that function is called:

  • A new object in case of a constructor.
  • undefined in strict mode function calls.
  • The parent object of the function is called an object method.

For example, Here is a person object which has the fullName() function:

const person = {
  firstName: 'Mike',
  lastName: 'Lilly',
  fullName: function () {
    return `${this.firstName} ${this.lastName}`
  }
}

person.fullName() // Mike Lilly

The fullName() method of the person object returns the person's full name.

However, an arrow function does not have the this keywork and is lexically bound. It essentially means that the this scope is inherited from the code that contains the arrow function.

While looking up for this that is not present in the current scope, the ES6 arrow function will use the value of this in the scope in which it was defined. That is why the call to fullName() will not work and will return an undefined value:

const person = {
  firstName: 'Mike',
  lastName: 'Lilly',
  fullName: () => {
    return `${this.firstName} ${this.lastName}`
  }
}

person.fullName() // undefined undefined

Become of this, arrow functions are not suited to object methods. You should also not use them as constructors either to avoid errors.

DOM Event Handling

Arrow functions can be a problem while handling events. DOM event listeners set this to be the target element. Now, if you use the arrow function for callbacks, the this keyword won't be bound to the target element but to its parent scope.

const button = document.getElementsByTagName('button')
button.addEventListener('click', () => {
  this.classList.toggle('blur')
})

If you click the button, you will get a TypeError because this refers to the window object in this scope. If you need a dynamic context for the callback function, a regular function expression is required:

const button = document.getElementsByTagName('button')
button.addEventListener('click', function () {
  this.classList.toggle('blur')
})

Conclusion

Arrow functions provide a new way of writing concise functions in ES6. They are shorter, have no binding of this keyword, implicitly return a value with the concise body, and are widely used in modern codebases. Arrow functions are inappropriate as object methods and cannot be used as constructors.

✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.

You might also like...

Digital Ocean

The simplest cloud platform for developers & teams. Start with a $200 free credit.

Buy me a coffee ☕

If you enjoy reading my articles and want to help me out paying bills, please consider buying me a coffee ($5) or two ($10). I will be highly grateful to you ✌️

Enter the number of coffees below:

✨ Learn to build modern web applications using JavaScript and Spring Boot

I started this blog as a place to share everything I have learned in the last decade. I write about modern JavaScript, Node.js, Spring Boot, core Java, RESTful APIs, and all things web development.

The newsletter is sent every week and includes early access to clear, concise, and easy-to-follow tutorials, and other stuff I think you'd enjoy! No spam ever, unsubscribe at any time.