Why I Hated (and Now Love) Arrow Functions

Earlier this week I gave a presentation (I'll share the links for that in a post later today) about the changing nature of JavaScript and as part of that, I quickly mentioned a few modern features that I really dig. One of them was arrow functions. A follower on Twitter asked if I could spend a bit more time on them so I thought I'd whip up a quick blog post. Let me start though with why I absolutely hated them.

Arrow functions have two main aspects. First, they are a new way of writing functions. Secondly, they handle "This" scope issues. The later is something I was fully behind. If you've ever seen that.x = this.x, then you'll recognize the issue. (And I'll share an example later.) The former though... filled me with deep and utter rage. Ok, I'm being a bit over the top, but at least to me, the syntax change in arrow functions was so radical that I had a mental block just trying to read them. It felt like one of those things developers do to be "cute"/"cool" without any real practical benefit.

Let me share an example.

document.addEventListener('DOMContentLoaded', e => {
  console.log('dom loaded like a boss');
}, false);

If you've never seen an arrow function before, that can be near incomprehensible. I'd see code using this form and my brain would come to an immediate stop while it attempted to "rewrite" it in the old school form. In order to really appreciate them, I had to start writing them, and every time I used one, I felt more and more comfortable with it and appreciated the terseness. I said earlier it felt like it was being cute for no real reason, but now it feels as natural as array shorthand (x = [1,2,]).

To understand arrow functions, let's consider an sample function and then rewrite it.

function hello(name) {
    return "Hi, "+name;
}

(As an aside, I normally use template literals when building strings in JavaScript now, but I don't want to put too much new syntax in a sample at once.) The code sample above defines a function named hello that takes one argument and has one line of body code. Remember that a function can also be defined like so:

hello = function(name) {
    return "Hi, "+name;
}

Ok, so the first thing you do when switching to an arrow function is dump the word function:

hello = (name) {
    return "Hi, "+name;
}

Next, you add the arrow.

hello = (name) => {
    return "Hi, "+name;
}

And you're done. But arrow functions let you go even simpler. If you only have one argument, you can drop the parens:

hello = name => {
    return "Hi, "+name;
}

And if you only have one statement, you can remove the brackets:

hello = name => "Hi, "+name;

Notice I also removed the return. The execution of "Hi, "+name returns a string and a function will automatically return the last statement result.

Remember though that the only required aspects of an arrow function are the removal of the word function and the addition of the arrow. If that last version looks too short to you, you can add the brackets back in. Also, maybe your function has one statement now but you're pretty confident it is going to grow. For example, you have a function that returns a boolean and for now you just want to return true.

Here is an example of a function that takes two arguments - both before and after:


function greet(greeting, name) {
    return greeting + " " + name;
}

greet = (greeting, name) => greeting + " " + name;

Here is another example where the function is multiple lines:


function greet(greeting, name) {
    var tempString = greeting + " " + name;
    if(tempString.length > 50) tempString = tempString.substr(0,50);
    return tempString;
}

greet = (greeting, name) => {
    var tempString = greeting + " " + name;
    if(tempString.length > 50) tempString = tempString.substr(0,50);
    return tempString;
}

I'm also ignoring another modern feature, let, in the code above, because I don't want to put too much in front of you at once.

Arrow functions work really well, in my opinion, in call backs. The very first example I gave demonstrated this, but here it is again, along with the "old" version:


document.addEventListener('DOMContentLoaded', function(e) {
  console.log('dom loaded like a boss');
}, false);

document.addEventListener('DOMContentLoaded', e => {
  console.log('dom loaded like a boss');
}, false);

It isn't a huge change, but it feels more compact, and since callbacks like this are littered everywhere in most JavaScript files, the shorter syntax really feels like a boon.

The other benefit of arrow functions are how they correct issues with this. If you've ever written a call back and realized that this.something inside wasn't working correctly, this is something you'll appreciate. For an example, I'm going to "borrow" the one MDN uses (I'll be linking to it in a moment). Consider this code:

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

  setInterval(function growUp() {
    this.age++;
  }, 1000);
}

var p = new Person();

If you run this and inspect the value of p, you'll see that age never increases. That's because the this in the callback is it's own scope, not the one for the Person function. A common fix was to simply add that = this and refer to that.age. But that's smelly. Consider the arrow function version:

function Person(){
  this.age = 0;

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

var p = new Person();

Boom - just plain works. By the way, if the (() => { part confuses you, remember that the () portion is the argument list, which in this case is empty.

So yeah - I love these things now. I'll be honest - they still don't quite flow off the tongue (or off my fingers) as fast as "old school" functions, but they are getting more and more familiar to me. Alright, how about some resources?

I'd love to hear from my readers. Are you using this yet? If so, what do you think, and if not, why?

Like This?

If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can also subscribe to the email feed to get notified of new posts.