# Introduction to JavaScript Arrow Functions

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published May 9, 2019, updated Oct 5, 2022. Topics: JavaScript.
Canonical URL: https://attacomsian.com/blog/javascript-arrow-functions

> Learn what are ES6's arrow functions and how to use them to write concise functions in JavaScript.

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:

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

absolute(-9) //9
```

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

```javascript
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:

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

## Function Parameters

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

```javascript
const pi = () => Math.PI
```

You can even replace empty parentheses with `_`:

```javascript
const pi = _ => Math.PI
```

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

```javascript
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:

```javascript
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):

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

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

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

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

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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.

```javascript
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:

```javascript
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.
