Arrow Functions: JavaScript ES6 Feature Series (Pt 2)
Tags: javascript, es6
Published: 2024-06-26 17:48:58

---
title: Arrow Functions: JavaScript ES6 Feature Series (Pt 2)
published: true
date: 2019-08-06 00:00:00 UTC
tags: javascript,es6
canonical_url: https://www.paigeniedringhaus.com/blog/arrow-functions-java-script-es-6-feature-series-pt-2
---

[![Old, beat up chalkboard with scribbled math on it](https://www.paigeniedringhaus.com/static/139cee556a38bbbaeb6d4ece403e962d/8efd0/chalkboard-hero.webp "Old, beat up chalkboard with scribbled math on it")](/static/139cee556a38bbbaeb6d4ece403e962d/14846/chalkboard-hero.webp)

## Introduction

The inspiration behind this series of posts is simple: there are still plenty of developers for whom JavaScript makes no sense sometimes — or at the very least, has seemingly odd behavior compared to other programming languages.

Since it is such a popular and widely used language though, I wanted to provide a bunch of posts about JavaScript ES6 features that I use regularly, for developers to reference.

The aim is for these articles to be short but still in-depth explanations about various improvements to the language, that I hope will inspire you to write some really cool stuff using JS. Who knows, you might even learn something new along the way. 😄

**For the second post in this series, I wanted to dive into arrow functions, and how they differ from traditional function declarations and function expressions.**

---

## Function declarations

You may have heard this before, but it bears repeating: **in JavaScript, functions are first-class objects** , because they can have properties and methods just like any other object. What distinguishes them from other objects is that functions can be called. In brief, they are [**`Function`**](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function) objects.

From here on, I will assume you’re familiar with the general idea of functions in JavaScript, But before I talk about arrow functions, it’s worth talking a little about both function declarations (also known as function statements) and function expressions.

[**Function declarations**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function) are the most basic function statement we see all the time in JavaScript. It defines a function along with the specified parameters it needs to run.

Here’s an example:

### Anatomy of a function declaration

```javascript
function multiply(number1, number2){
  return number1 * number2;
}

console.log(multiply(4, 9));  
// prints 36 to the console
```

If you’re looking at the function declaration example above, here’s what composes the function. `multiply` is the **name** of the function, `number1` and `number2` are the two **parameters** the function takes in, and the body of the function: `return number1 * number2;` is the **statement**.

### Function declaration traits

Function declarations have certain traits which developers need to keep in mind as they write code, because they will trip you up at one time or another — they manage to trip us all up (myself included). 🙋

**1. Functions return undefined, unless otherwise specified**

By default functions return `undefined`. By including the `return` keyword in the body, you can specify the value it returns instead.

**Function declarations undefined vs. returned values**

```javascript
function returnsNothing(item1, item2) {
  item1 + item2;
}

console.log(returnsNothing(1, 9)); 
// prints: undefined

function returnsSomething(item1, item2) {
  return item1 + item2;
}

console.log(returnsSomething(1, 9)); 
// prints: 10
```

For my example above, the sum of `item1` and `item2` is what is returned from the `returnsSomething()` function, while the `returnsNothing()` function, although it does exactly the same addition, merely returns `undefined` when the value is called with `console.log()`.

**2. Function declarations are hoisted**

Similar to variable hoisting, which I discussed in my [previous blog post](https://www.paigeniedringhaus.com/blog/var-let-const-java-script-es-6-feature-series-pt-1), function declarations in JavaScript are **hoisted** to the top of the enclosing function or global scope. This means, you can use a function before it’s actually been declared in the code.

**Function declaration hoisting vs. function expression not hoisting**

```javascript
console.log(hoistedFunction()); 
// prints: "Hello, I work even though I am called before being declared"

function hoistedFunction() {
  return "Hello, I work even though I am called before being declared";
}

console.log(notHoisted());
 // prints: TypeError: notHoisted is not a function

var notHoisted = function() {
  return "I am not hoisted, so I will not be found if called before my declaration";
}

console.log(notHoisted()); 
// prints: "I am not hoisted, so I will not be found if called before my declaration"
```

In the above example, the function `hoistedFunction()` returns its value, regardless of when it’s called in the code, because it’s a function declaration.

On the other hand, the second function assigned to the variable `notHoisted()`, which is a function expression, is not hoisted to the top of the scope so if it is invoked before the function is parsed, it throws a `TypeError` in the code that it is not a function (mainly because the compiler’s not aware of it yet).

Those are main things you need to be aware of when thinking about function declarations.

Let’s move on to function expressions.

## Function expressions

[**Function expressions**](https://developer.mozilla.org/en-US/docs/web/JavaScript/Reference/Operators/function) are similar to function declarations. They still have names (which are optional this time), parameters, and body-based statements.

### Anatomy of a function expression

```javascript
const divide = function(number1, number2){
  return number1 / number2;
}

console.log(divide(15, 5)); 
// prints: 3
```

For this example, the variable `divide()` is assigned to the anonymous function which takes the parameters `number1` and `number2`, and returns the quotient as per the body’s statement `return number1 / number2;`.

### Function expression traits

Just like function declarations, function expressions have some defining quirks of their own. Here’s what you need to know about them.

**1. Function expressions can be anonymous (or not)**

As I mentioned briefly above, function expressions, since they’re assigned to variables, can omit a name, and be what’s known as an "anonymous function". This is possible because the variable name will be _implicitly_ assigned to the function.

**Anonymous function expression (implicit naming at work)**

```javascript
const anonymous = function() {
  return "I do not need my own name, as I am assigned to the variable anonymous";
}

console.log(anonymous()); 
// prints: "I do not need my own name, as I am assigned to the variable anonymous"
```

As the variable name implies, since the function it’s referencing has no name, it implicitly assigns `anonymous()` to the function.

If, however, you want to refer to the current function inside the function body, you need to create an _explicitly_ named function (whose name is local only to the function body).

**Named function expression (explicit naming at work)**

```javascript
var math = {
  "factit": function factorial(n) {
    console.log(n)
    if (n <= 1) {
      return 1;
    }
    return n * factorial(n - 1);
  }
};

console.log(math.factit(3)); 
//prints: 3; 2; 1;
```

For this variable `math`, you can call the `factorial()` function by invoking `math.factit();` outside of the object, and passing the required parameter in.

> I don’t find as much need for this type of named function expression in my day to day development, but it’s nice to know it’s available if the need arises.

**Bottom line:** If the function expression’s name is omitted, it will be given the variable name (implicit name). If the function expression’s name is present, it will be the assigned function name (explicit name).

**2. Function expressions can be IIFEs**

A function expression can be used as an IIFE: an [Immediately Invoked Functional Expression](https://developer.mozilla.org/en-US/docs/Glossary/IIFE), which runs as soon as it’s defined.

This immediate execution by the JavaScript engine is triggered by the parentheses `()` at the end of the anonymous function.

I won’t go into too much detail here, but for any variables created within the IIFE to be accessible to the outside or global scope, the anonymous function must be assigned a variable a la a function expression.

If it’s not and the anonymous function’s just invoked at run time, any variables created inside the function’s scope will be invisible to the outside world.

**IIFE variables that are accessible vs. IIFEs that are not**

```javascript
const cogitoErgoSum = (function () {
  const quote = "I think therefore I am";
  return quote;
})();

// immediately creates the output
cogitoErgoSum; 
// prints: "I think therefore I am"

(function (){
  const quote2 = "I am not outside this IIFE";
})();

quote2; 
// prints: ReferenceError: quote2 is not defined
```

**3. Function expressions don't hoist**

Function expressions (and arrow functions) take after the new `let` and `const` variable keywords, in that they don’t get hoisted at run time.

As I demonstrated above in the function declaration section around hoisting, function expressions **do not hoist** , a function expression is created when the execution reaches it and it is usable from then on.

**Function declaration hoisting vs. function expression not hoisting**

```javascript
console.log(hoistedFunction()); 
// prints: "I am a function declaration so I am hoisted to the top of the scope at run time"

function hoistedFunction() {
  return "I am a function declaration so I am hoisted to the top of the scope at run time";
}

console.log(stillNotHoisted()); 
// prints: TypeError: stillNotHoisted is not a function

const stillNotHoisted = function() {
  return "I am a function expression and therefore, hoisting does not apply to me";
}

console.log(stillNotHoisted());
 // prints: "I am a function expression and therefore, hoisting does not apply to me"
```

The outcome is the same as when I described it in function declarations, function expressions throw `TypeErrors` if invoked before they are parsed at run time. Just don’t do it.

Ok, now time to move on to arrow functions: the latest and greatest function improvements courtesy of ES6.

## Arrow function expressions ➡️

[![Arrow function syntax](https://www.paigeniedringhaus.com/static/989603bb6685b9c6b40ff2407b0a2772/63d40/arrow-func.webp "Arrow function syntax")](/static/989603bb6685b9c6b40ff2407b0a2772/63d40/arrow-func.webp)

_The most basic arrow function syntax._

[**Arrow function expressions**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) are syntactically compact alternatives to regular function expressions.

### Anatomy of two basic arrow function expressions

```javascript
const basicArrow = () => {
  return "The most basic of basic arrow functions";
}

basicArrow(); 
// prints: "The most basic of basic arrow functions"

const basicArrow2 = oneParam => `Single line with ${oneParam} is also valid`;

basicArrow2("only one param"); 
// prints: "Single line with only on param is also valid" 
```

Both of the examples above `basicArrow()` and `basicArrow2()` are valid examples of an arrow function. As with all function expressions, both anonymous functions are implicitly named by the variables assigned to them.

What’s different though is that the `function` keyword is unnecessary. Instead it’s replaced by a set of parentheses `()` if there are no required parameters, the name of the single parameter required by `basicArrow2()`, which is `oneParam` (no parentheses necessary in this case), or, for any other number of parameters, you could do `(paramOne, paramTwo, paramThree, ...)`.

Similarly, the first function has a normal `return` statement inside the body of the function surrounded by curly braces `{}` but, if the statement is super simple, and you can fit the return on a single line, the actual `return` and curly braces can also be omitted, like in `basicArrow2()`. This is concise body syntax with an implied return statement.

### Arrow function traits

While arrow functions are easy to identify at first glance, they actually have some traits which are odd and specific to them, and which developers need to keep in mind.

In addition to their concise syntax, arrow functions lack the [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this), [arguments](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments), [super](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super), or [new.target](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target) keywords.

These facts also lend themselves to one of the arrow function’s biggest drawbacks: they are ill suited as methods and cannot be used as constructors. I’ll get to that in more detail soon.

**1. Shorter function syntax**

The first, and biggest improvement, in my opinion, to regular function expressions is the shorter, more concise syntax that arrow functions offer.

Here’s the exact same function written as a traditional function expression, then written again as an arrow function expression.

**Traditional function expression**

```javascript
var elements = ["Hydrogen", "Helium", "Lithium", "Beryllium"];

elements.map(function(element) {
  return element.length;
});
// this statement returns the array: [8, 6, 7, 9]
```

**New arrow function expression**

```javascript
var elements = ["Hydrogen", "Helium", "Lithium", "Beryllium"];

elements.map((element) => element.length);
// this statement still returns the same array: [8, 6, 7, 9]
```

Look at those and tell me the second function isn’t easier to read and follow what the code is doing.

That by itself, is my biggest reason to want to use arrow functions whenever possible. It’s just so much cleaner and clearer.

**2. Hoisting still doesn't apply**

Just like with traditional function expressions, hoisting still does not apply to arrow functions.

**No hoisting, only `TypeErrors`**

```javascript
console.log(fish()); 
// prints: TypeError: fish is not a function

const fish = () => ["perch", "salmon", "trout", "bass"];

console.log(fish());
// prints: ["perch", "salmon", "trout", "bass"]
```

If you try to call the `fish()` function before it’s declared in the code, a `TypeError` will be thrown.

The solution, as before, is to either declare the function as a function declaration so it gets hoisted to the top of the scope, or wait until after the function expression to call the code.

**3. No separate "this"**

Before arrow functions, every new function defined its own [`this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) value based on how the function was called:

- A new object in the case of a constructor,
- `undefined` in strict mode function calls,
- The base object if the function was called as an "object method".

An arrow function, on the other hand, does not have its own `this`.

The `this` value of the enclosing lexical scope is used. Arrow functions follow the normal variable lookup rules of starting at the current scope level and searching all the way to the highest level looking for the variable. So while searching for `this` which is not present in the current scope, an arrow function ends up finding the this object from its enclosing scope.

See the example below to see the difference.

**`this` scope, according to function declarations**

```javascript
function Person() {
  // The Person() constructor defines `this` as an instance of itself.
  this.age = 0;

  setInterval(function growUp() {
    // In non-strict mode, the growUp() function defines `this`
    // as the global object (because it's where growUp() is executed.), 
    // which is different from the `this`
    // defined by the Person() constructor.
    this.age++;
  }, 1000);
}

var p = new Person();
```

**`this` scope, according to arrow functions**

```javascript
function Person(){
  this.age = 0;

  setInterval(() => {
    // `this` properly refers to the Person object
    this.age++; 
  }, 1000);
}

var p = new Person();
```

**4. No binding of arguments**

In addition to not having access to `this`, arrow functions do not have their own [`arguments` object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments).

Since you may not have heard of them, `arguments` is an `Array`-like object inside a function that contains the values passed to that function. I say `Array`-like because this `arguments` has a length property and indexing but it lacks Array’s built-in methods like `.forEach()` and `.map()`.

Thus, in this example, `arguments` is simply a reference to the arguments of the enclosing scope.

**`arguments` with arrow functions**

```javascript
var arguments = [1, 2, 3];
var arr = () => arguments[0];

arr(); 
// prints: 1

function foo(n) {
  var f = () => arguments[0] + n; 
  // foo's implicit arguments binding. arguments[0] is n
  return f();
}

foo(3); 
// prints: 6
```

In most cases, using [rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) is a good alternative to using an `arguments` object.

**Rest parameters instead of `arguments` with arrow functions**

```javascript
function foo(n) { 
  var f = (...args) => args[0] + n;
  return f(10); 
}

foo(1); 
// prints: 11
```

The rest parameters, which I’ll discuss in another blog post later in this series, is the ES6-recommended way of accessing and manipulating `arguments` inside of arrow functions.

**5. No use of "new" as a constructor**

Ok, last arrow function trait to know about: arrow functions cannot be used as constructors and will throw a `TypeError` when used with the `new` keyword.

```javascript
var Foo = () => {};

var foo = new Foo(); 
// prints: TypeError: Foo is not a constructor
```

And that’s it. That’s generally what you need to know about arrow functions. Simple! 😅

---

## Conclusion

JavaScript is an incredibly powerful programming language, and its popularity only continues to increase (if the yearly developer surveys are to be believed). With so many developers using it though, there’s bound to be some misconceptions and knowledge gaps, especially with the growing widespread adoption of ES6 into everyday use.

My aim is to shed light on some of the JavaScript and ES6 syntax you use everyday, but may never have fully grasped the nuances of why it works the way it works.

Functions of all kinds are a staple of JavaScript, be they traditional function declarations or function expressions, or the newer, more concise ES6 arrow functions. Knowing when (and how to) effectively take advantage of the benefits of each type of function will definitely make writing JS easier.

Check back in a few weeks, I’ll be writing about JavaScript, ES6 or something else related to web development.

If you’d like to make sure you never miss an article I write, sign up for my newsletter here: https://paigeniedringhaus.substack.com

Thanks for reading, I hope you feel better equipped to incorporate arrow functions into your JavaScript applications. Please share this with your friends if you found it helpful!

---

## References & Further Resources

- [Function declaration, MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)
- [Function expression, MDN docs](https://developer.mozilla.org/en-US/docs/web/JavaScript/Reference/Operators/function)
- [Arrow functions, MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)