ES6 Arrow Function Tutorial

ES6 Arrow Function Tutorial

Let’s take a look at ES6 arrow functions. If you’ve spent any amount of time programming JavaScript, you know that after awhile, it feels like you’re typing out that function keyword over and over and over. You write a function here, you write a function there. Here a function, there a function, every where a function function. That’s because anytime you want something to actually happen in your script, you need to write another function! Have you ever thought, “it might be nice if I didn’t have to write out the function keyword so darn often”. If so, you’re in luck with ES6, because there is a new shorthand for writing functions and they are referred to as ES6 Arrow Functions. Let’s investigate them a little bit now.

Arrow Functions use Fat Arrow Syntax

You may have heard of these new arrow functions as using the fat arrow syntax. This is because this new symbol for defining functions in ES6 is the combination of an equals sign = and a greater than symbol >. Put them together and now you have your fat arrow =>. The equals sign is what makes the arrow fat. So let’s start off by creating a function in ES5, and then see what we have to do in order to turn it into an ES6 Arrow Function.

Here is an example of a simple addition function in ES5

We can rewrite this function using fat arrows => in a couple of steps.

  • 1. Delete the function keyword to the left of the function arguments
  • 2. Insert a fat arrow to the right of the function arguments

Your first arrow function

Congratulations! You have just created your very first arrow function in ES6! Let’s take it a step further.

You can omit the return keyword for simple expressions by placing everything on one line and removing the brackets or curly braces like so.

Finally, if there is only one argument for the function, you can even leave off the parenthesis like so.

You now have less chance of developing carpel tunnel syndrome from the repetitive stress of typing function so much.

Arrow functions with no input must make use of parenthesis

In this example below, we create a super simple arrow function and assign it to the points variable. In contrast to the example above where we square a number via a function and it requires a number as a parameter, this function here has no parameter. If there are no parameters at all to an arrow function, you must make use of the empty parenthesis syntax.

Screenshot of the arrow function highlighted

This screenshot highlights the area in the code that makes up the arrow function. Note the lack of parameters, return statement, or curly braces.
es6 arrow function

Logging out a call to the arrow function

If we log out the value of a call to the points() function, we can see we get the result of 100. You see, the code is actually handling the return of the value for us, we do not need to specify it manually by typing the return keyword.

Single argument arrow function example

The only time you can use no parenthesis is when there is one argument to an arrow function. This might be a little confusing. If you’d rather follow a convention of just using the parenthesis in all use cases of an ES6 arrow function, you can do that. This example here of a one argument ES6 arrow function works just fine when we include the parenthesis.

The same function works the same way if we omit the parenthesis.

Another example of multiple arguments using parenthesis

Making use of blocks or brackets with arrow functions

Single line arrow functions are perfect for simple expressions. More often than not, you are going to need to make use of functions that do more than just a simple expression that can fit on one line. In that case, you can certainly make use of brackets like you are so used to doing when defining functions. One key thing to remember when using brackets with arrow functions: You must include the return keyword to return a value from your function. The return of a value will not happen automatically like it would with a single line arrow function. Keep this in mind.

Multi line arrow function highlighted

multi line arrow function in ES6

Where the Fat Arrow does not make sense

Now that you’re familiar with fat arrows and how to type less, while making your code more terse, you’re probably ready to remove every trace of a function keyword in any project you’re working on. Not so fast cowboy. Fat arrows do not make sense everywhere. Typically you will avoid using the fat arrow in constructor functions as well as any prototype extensions. If you’re using ES6, you’ll likely be making use of the class syntax anyway, so you won’t have to worry about that too much. It is a good point to keep in mind however.

this is different in ES6 vs ES5!

You are likely very familiar with how this works in ES5. To be honest, it’s pretty confusing and there are a whole slew of rules that determine what this actually points to at any given time in your JavaScript code. Arrow functions in ES6 take all the rules of how to use this in ES5, and throw them right out the window. In ES6, arrow functions come with automatic context binding. The goal of this is to hopefully make it easier to use the this keyword, since you shouldn’t have to worry about context binding so much anymore. Consider this snippet of ES5 code attaching a click event to the document.

In ES5 whenever we have an event handler in our code, this gets set to the element that receives the event. This results in not having access to the context of the function.

Let’s now change this code up to make use of an arrow function, and see how this impacts this.

This time around, since we are using an arrow function, this gets set to the global Window object since we are in the global scope. We are not in the context of a function. With the arrow function, this refers to the actual context of the code we are running.

Taking this idea a bit further, let’s look at calling functions that exist in objects in ES5 vs ES6.

This shows that in this example, this is getting set to the object on which the function is called.

What happens if we change this to use an arrow function. Let’s see.

With the arrow function in place, we get the context of the code we are running. Or in other words, what scope is this particular code operating in? In this case it is the global scope, therefore we get the global Window object since this is what represents the global scope.

Function context in ES6

This example is an object literal which has a servicenumber value, and a process function. That process function, actually returns a function. Then we call the process function, and immediately call the returned function. This is what is meant by bill.process()(); So what is happening with this inside the returned function? Well, the arrow function is executing within the context of another function, and this is why we see the value of this.servicenumber rather than the global Window object.

bind does not work with arrow functions!

Taking the prior code a step further, we create another object literal that also has a servicenumber property. You may be familiar with calling the bind() method in ES5 to set the context as you choose. Let’s test it out here with an arrow function.

Now check that out! You would think that the servicenumber would be 900, since we tried to bind the newBill object literal to our process function. This does not work however with ES6 arrow functions. This did not produce any errors or anything, so if you did not know any better, you would have no clue why bind() was failing. With ES6 Arrow Functions, you can not use bind().

Just like the example above, making use of call() also does not work!

With ES6 arrow functions, using bind(), call(), and apply(), are all useless! You can not change the value of this.

Fat arrows can not go on a new line

Here is just a quick tip regarding the syntax of arrow functions. You can not place the fat arrow on a new line, or the script will fail.

You’ll need to keep the fat arrow on the same line, and you’ll be ok.

Arrow functions have no prototype

Another interesting thing to keep in mind with arrow functions, is that they have no prototype property. Functions declared using the function keyword do have a prototype property.

Let’s look at some examples of using the new class syntax in ES6. These first two examples make use of this, but it is not in the context of an arrow function. This is just to get ourselves familiar with the syntax before testing out this within an arrow function in more complex code.

Using ES5 function in the log function

Using an arrow function in the log function

In both of the above examples, we get the same result whether we are using ES5 functions of ES6 arrow functions in the log function. Each type does not make use of the this keyword, so that is to be expected.

Let’s now change things up to make use of the this keyword within the log function to see what happens.

Note that this inside the log function is now undefined.

How about if we turn that into an ES6 arrow function? Let’s see what happens.

In this example above, this refers to each instance of the GamesCollection Object as you iterate through them.

Testing this against different instances of an object

Let’s look at one more example of how this is bound in arrow functions vs ES5 functions. Below, we set up a constructor for a Language. We then extend the prototype of Language with a greet() function. This function simply logs out it’s name after a short delay.

Nice! In this first example, we are using an arrow function and when we call the greet function on two different objects, this automatically points to the correct instance.

Let us now remove the arrow function and replace it with an ES5 style function. We get different results.

Now, the code breaks because this now points to the global Window object, rather than any instance of Language.

To fix this issue in ES5, we had to make use of bind() like so

The code now works again when using ES5 functions and bind().

ES6 Arrow Function Tutorial

Congratulations, you are now a Boss at using arrow functions in ES6! Well, maybe not boss mode quite yet, but this tutorial covered a lot of what you’ll need to know in order to make good use of arrow functions in your ES6 code. What are the main points? The use cases for fat arrows are syntactic sugar, and a more compact way of writing functions. In ES6, arrow functions come with automatic context binding, which should help with not having to worry about maintaining context binding manually via bind(), call(), or apply(). In constructor functions and prototype extensions, it does not make sense to use fat arrow syntax. You can continue to use the function keyword in those scenarios.