Profile picture of Marc Backes (very handsome) Profile picture of Marc Backes (very handsome)
Marc Backes

Difference Between Arrow Functions And Regular JavaScript Functions

June 28, 2019 · by Marc Backes
Profile picture of Marc Backes (very handsome) Profile picture of Marc Backes (very handsome)
Difference Between Arrow Functions And Regular JavaScript Functions Difference Between Arrow Functions And Regular JavaScript Functions

In my quest to getting to know ES6, I used the new sexy "arrow functions" quite a lot lately. But until today, I didn't understand why they were necessary and that there even is a difference between arrow functions and "normal" functions 🤯. (Spoiler: No, it's not just to be quicker to write).

What are arrow functions? 🧐

Arrow functions are the new ES6-way to define functions. Let's write a function that calculates the square of a number with the ES5 syntax:

const doubleDown = function (a) {
  return a * 2
}

In ES6, it would look something like this:

const doubleDown = a => {
  return a * 2
}

Two more arrow function features could make this even shorter:

  • If there is only one parameter, we don't need to put the brackets
  • If the function is a one-line-return-function (as above), we don't even need the curly brackets and the return statement

Applying all of this gives us the following code:

const doubleDown = a => a * 2

Neat! We have a sexy little ES6 function.

What is the difference between the two? 🤷‍♂️

Short version: Arrow functions don't have their own this-binding. What what? Let me try to explain how I understood it.

How arrow functions behave with objects

When we add a function as a property to an object, it's called a method. In a method, you can access the this keyword to access other properties of the same object, as follows: this.myProperty

So, we have an object here that is an object that contains comic heroes and we want to print out a title that includes a property of the object (universe). Again, first in ES5 writing:

const comics = {
  universe: 'marvel',
  heroes: ['spiderman', 'thor', 'black widow', 'deadpool'],

  // Regular function
  printTitle: function () {
    console.log(`hello from ${this.universe} comics`)
  },

  // Arrow function
  printTitleAF: () => {
    console.log(`hello from ${this.universe} comics`)
  },
}
comics.printTitle()
comics.printTitleAF()

So, here we have some heroes from a specified comic universe. We want to print a title with a regular function printTitle and to compare it with an arrow function printTitleAF.

Since the code is the same, the result of both should be the same, right? No, that's not the case. Here it the output of the code above:

hello from marvel comics
hello from undefined comics

This seems weird now but will make more sense in a minute. this in the regular function refers to the object itself, while this in the arrow function does not bind!

ES6 Arrow Functions

As you can see in the image above, the this keyword behaves differently in both functions, even though they are seemingly the same.

That is because this in the case of a regular function points as expected to the object, but this in the arrow function points to an empty object.

How to use ES6 functions like a boss 😎

Nice way to write property functions in ES6

So, the arrow function notion cannot be used to define property functions. However, there is a cleaner way to write them in ES6. Just leave the colon and function keyword out:

const comics = {
  universe: 'marvel',
  heroes: ['spiderman', 'thor', 'black widow', 'deadpool'],

  // ES6 property function
  printTitle() {
    console.log(`hello from ${this.universe} comics`)
  },
}

When you can use arrow functions

Arrow functions are useful whenever you have something that requires this not to be bound to function itself, but rather the context—for example, passing it as a parameter to another function such as Array.forEach or setTimeout.

// ES6 version
const comics = {
    universe: "marvel",
    heroes: ['spiderman', 'thor', 'black widow', 'deadpool'],

    printTitle() {
        console.log(`hello from ${this.universe} comics`);
    }

    printHeroes() {
        // Passing an arrow function as parameter to forEach
        this.heroes.forEach(function(hero) {
            console.log(` - ${hero} is part of the ${this.universe} universe`);
        });
    }
};

That works fine because this is not bound to the function itself.

How can I do that in ES5?

Now you might be thinking, "ok cool, but what if I am using ES5 in a project and need that exact behavior?"

Well, then you need to build a dirty workaround that you can find in many places. You place this in variable:

// ES5 version
var comics = {
    universe: "marvel",
    heroes: ['spiderman', 'thor', 'black widow', 'deadpool'],

    printTitle: function() {
        console.log(`hello from ${this.universe} comics`);
    }

    printHeroes: function() {
        var that = this; //Dirty hack here
        this.heroes.forEach(function(hero) {
            console.log(` - ${hero} is part of the ${that.universe} universe`);
        });
    }
};

Summary 🙌

The whole this topic is one of the most complicated and annoying things when learning JavaScript, and it behaves in strange ways. But I hope this explainer helped a little bit of understanding.

When you need the context you're working in within your function when you pass it somewhere; it can be very helpful to use it. But before using arrow functions, evaluate if it really is what you need.

I found for getting a better grasp at the topic, it's useful to write some code trying it out on yourself, and pretty soon, it will not be that a big mystery after all.