JavaScript isn’t the first language to use first class functions, but it’s likely the language that made them popular. Java, Objective C, C#, C++, Python… these are all languages that did not have first class functions until recently. Once JavaScript became one of the world’s most popular programming languages, other language designers realized just how useful first class functions really are, and have added first class functions to the languages mentioned above, as well as newer languages like Swift and Go.

If you recall from Chapter 10 of Head First JavaScript Programming, a first class value is one that can be assigned to a variable, passed as an argument, and returned from a function. In JavaScript, functions are values, and pass all three criteria for first class status in the language.

What’s the big deal? Well, think about how you typically create a timer event:

setTimeout(function() { 
   alert("Cookies are ready!"); 
}, 1000);

setTimeout takes two arguments: a function to be executed once the timer expires, and the time to wait before calling the function (in milliseconds). setTimeout takes care of calling the function once the 1000ms has passed. Being able to pass any function you like to setTimeout makes this code flexible, concise, and easy to understand.

Let’s take a look at another common use case for first class functions:

var even = [];
[1, 2, 3].forEach(function(x) { 
   even.push(x * 2); 
});

This code uses the array method forEach to double the values in an array. The resulting array, even, has the value: [2, 4, 6]. forEach takes a function as an argument, and applies that function to each value in the array. It’s a short and easy way to write a loop on an array.

Once you start programming in JavaScript, you’ll find first class functions everywhere. Currently, in JavaScript ES5 (the version implemented in most browsers today), we write all functions in the same way; once ES6 is implemented in browsers, you’ll likely start seeing arrow functions replace the functions you’re used to in many use cases like the ones we’ve seen above.

Arrow functions

So what is an arrow function? It’s a function, but differs from functions as you know them in JavaScript ES5 in two important ways. First, you write an arrow function using different syntax than you do for a regular function. An arrow function to add 2 to a value looks like this:

(x) => x + 2

Let’s take a look at what this means. Start with a regular function that does the same thing:

function add2(x) { return x + 2; }

Then, remove the function keyword and the name of the function, add2:

(x) { return x + 2; }

Now, add the arrow:

(x) => { return x + 2; }

You would keep the curly braces and the return if you had more than one statement in the function body, but because we have only one statement that returns the value of an expression, we can get rid of both the curly braces and the return:

(x) => x + 2

So, what’s on the left of the arrow is a list of parameters (much like the list of parameters that typically follows the function keyword in a regular function). And on the right of the arrow, in this case, is an expression that is evaluated when the function is called, and returns the result of the expression. The arrow function doesn’t have a name because arrow functions are designed to be used in place of anonymous functions.

Compare the original function with the arrow function and you can see that the arrow function is a lot more concise.

Let’s try using this function now (Firefox 38; arrow functions do not yet work in other browsers as of this writing):

function apply(f, n) {
    return f(n);
}

apply((x) => x + 2, 10);

The call to apply results in the value 12.

apply simply takes a function and a (number) value and calls the function, passing the number to the function. We can pass the arrow function we created to apply in exactly the same way as we’d pass a regular function.

Arrow functions are designed to be used whenever you would typically pass a short, anonymous function to another function (or, likewise, return a short, anonymous function from another function). With that in mind, let’s rewrite the previous two examples using arrow functions:

setTimeout(() => { 
   alert("Cookies are ready!"); 
}, 1000);

var even = [];
[1, 2, 3].forEach((x) => { 
   even.push(x * 2); 
});

Here, because we’re not returning a value from either of these functions, I use the curly braces to delimit the statement in the function body in both examples, even though it’s not strictly necessary (the functions can return undefined since we’re not relying on the return values). But any time you have multiple statements in the body of an arrow function you must use the curly braces, e.g.:

var numberToGuess = 3;
setTimeout(() => { 
   var guess = Math.floor(Math.random() * 10);
   if (guess == numberToGuess) {
       alert("You won!");
   } else {
       alert("Sorry, better luck next time.");
   }
}, 1000);

Here, we’re passing an arrow function to setTimeout that generates a random number and compares it to the variable numberToGuess. If the values are the same, you won, otherwise, better luck next time. Here, the arrow function behaves just like a regular function would; you just get to save a little bit of code by not writing the keyword function.

Okay, so you save a little bit of typing. Big deal. Sometimes it’s handy (particularly if your arrow functions are super short and just return a value, like we saw above with the add2 example).

But there’s another important difference between arrow functions and regular functions that will be very useful in some circumstances. And that is: arrow functions are pure functions—they are never methods. And that means that the way the value of this is handled in an arrow function is different from the way this is handled in a regular function. Let’s see how, next.

The value of this

Here, we have an object, beatBox, with a method play that takes an array of notes (strings) and plays the sample sound (“gong”) for each note. Our initial implementation of play uses a for loop to loop through all the notes in the sequence:

var beatBox = {
  sample: "gong",
  play: function(sequence) {
    for (var i = 0; i < sequence.length; i++) {
      var note = sequence[i];
      console.log("Play " + this.sample + 
                  " for note ", note);
    }
  }
};
beatBox.play(['A', 'C', 'F']);

This works fine. Notice that in this example, the value of this in the body of the play function is the object whose method we called; that is, beatBox. So when we refer to this.sample, we’re referring to the sample property of the beatBox object.

Now, let’s say you decide to replace the for loop in the code above with the forEach method on your sequence array:

var beatBox = {
  sample: "gong",
  play: function(sequence) {
    sequence.forEach(function(note) {
      console.log("Play " + this.sample + 
                  " for note ", note);
    });
  }
};
beatBox.play(['A', 'C', 'F']);

When you try to run this code, you’ll see the following output:

Play undefined for note A
Play undefined for note C
Play undefined for note F

The code this.sample is no longer working. That’s because of the way that JavaScript handles the value of this in functions that aren’t methods. We are passing a function to the forEach method of the array, and in that function, the value of this is the global object, window. (Try adding a log to the console inside the function to see!).

This is just the way that JavaScript works. When you have a function that’s not being called as a method, then, by default, that function is actually a method of the window object (or whatever the global object is, depending on your JavaScript environment). So, it’s as if the forEach method is calling window.function. And so, because this function is actually a method of window, the value of this is the window object!

We lose the value of this when we call another function inside the method play.

This issue has long plagued JavaScript programmers in precisely this situation. We have a couple of workarounds; a common pattern is to save the value of this in a variable defined where this is the object we want it to be (that is, in a context outside the function where its value is lost):

var beatBox = {
  sample: "gong",
  play: function(sequence) {
    var that = this;
    sequence.forEach(function(note) {
      console.log("Play " + that.sample + 
                  " for note ", note);
    });
  }
};
beatBox.play(['A', 'C', 'F']);

Try this code, and you’ll find it runs fine. What we’re doing here is saving the value of this in the variable that before we call the forEach method on the array (this value is the beatBox object). Then, we use that.sample instead of this.sample in the body of the function we pass to forEach. Notice that to find the value of that in the body of the function we’re passing to forEach, we use lexical scoping: we look first in the function itself to see if that is defined; it’s not, so we then look in the context surrounding the function (the play method), and it is, so that’s the value we use for that (the beatBox object).

(For a refresher on lexical scoping, refer to Chapter 11 of Head First JavaScript Programming).

Another common solution is to use bind:

var beatBox = {
  sample: "gong",
  play: function(sequence) {
    sequence.forEach(function(note) {
      console.log("Play " + this.sample + 
                  " for note ", note);
    }.bind(this));
  }
};
beatBox.play(['A', 'C', 'F']);

bind is a function method: you call bind on a function object, and pass in the object you want to use as this in the body of the function. bind returns a new function with this bound to the value you passed in.

(For more on how bind works, check out the Head First JavaScript Programming Extra I wrote on this topic).

Here, we’re passing this, the beatBox object, to use as the value for this in the body of the function we’re passing to the forEach array method. That means when we write this.sample, we get the property from the beatBox object, just as we wanted.

With arrow functions, we no longer need either of these solutions.

var beatBox = {
  sample: "gong",
  play: function(sequence) {
    sequence.forEach((note) => {
      console.log("Play " + this.sample + 
                  " for note ", note);
    });
  }
};
beatBox.play(['A', 'C', 'F']);

Here, we’ve replaced the function we’re passing to the forEach method with an arrow function. Remember that an arrow function is never called as a method; it’s a pure function, unlike when we used a regular function, which ends up being called as a method of the window object.

So how does JavaScript know what value to use for this in the body of the arrow function we’re passing to forEach? We use lexical scoping, just like we’d use to determine the value of any other unbound variable in the body of a function.

Using lexical scoping, we first look for a value for this defined in the arrow function. There isn’t one, so we look for a value for this defined in the context surrounding the arrow function, and we do find one: in the function play (which is the context surrounding the arrow function), this is defined to be the beatBox object. So that’s the value we use for this in the arrow function.

Try running this code in Firefox, and you’ll see that it works just fine.

Summary

So arrow functions differ from regular functions in two important ways: syntax, and how the value of this is determined. Syntax is easy to learn, but remembering that JavaScript now has two different ways of treating this in functions is a little trickier. It will take a little bit of time to get the hang of arrow functions in situations where you’re using this.

Note that this can never be set for arrow functions. Unlike a regular function where we can set the value of this using bind (like we did above), you can’t use bind (or call) with arrow functions to set the value of this. You can only use bind and call to set the values of arguments (in other words, the first argument to bind is just ignored). An arrow function will always determine the value of this using lexical scoping.

Now you might be thinking: there are many situations where I could use either a regular function or an arrow function and it wouldn’t make any difference (e.g. our add2 function above). So which is better?

It really depends on the situation. Both arrow functions and regular functions have their place, particularly if you are concerned about the value of this. Arrow functions can sometimes be considerably shorter than regular functions to write (although not always). So, it’s really up to you which one you use.

The key thing to know is that now JavaScript has two different kinds of functions: regular functions, which are always called as methods of objects—explicitly, or implicitly with the window object—, and arrow functions, which are never called as methods of objects.

There’s one more use case for functions we haven’t looked at yet, and that is how we use functions to create new objects. I’ll talk about how that’s changing in ES6 in my next blog post.

Resources

Don't miss out!

Don't miss out on brain-friendly WickedlySmart updates early access to books and general cool stuff! Just give us your email and we'll send you something about once a week. 

You have Successfully Subscribed!