Fat Arrow Functions in JavaScript

windmills panorama

Hard to beat C# and CoffeeScript here
– Brendan Eich, Arrow Function Syntax Rationale

Since sometime back in the heady days of Firefox 22, Firefox gained the ability to use Fat Arrow Functions in JavaScript. Users of CoffeeScript (or, I guess, C#) will be familiar with the syntax. We’ve been using these in Firefox DevTools code for nearly 6 months.

You can use them today in any shipping Firefox and experiment with them live in the Scratchpad or Console.

They look like this:

let x = (args) => { /* some function gunk */ };

If you want to call it, you can with x();

Fat Arrow functions have a couple of interesting properties. First and probably most useful is that they gain the scope of the environment they’re defined in. You can’t change the value of this by using a call() or bind() function.

Second, Fat Arrow functions don’t have their own prototype or a constructor. (They have the standard Function prototype). This means trying to use the new operator on a fat arrow function results in a TypeError.

That’s all well and good, but what is the practical application of all of this? If you’re a JavaScript programmer, chances are you’ve seen (and done) something like this before:

var listener = node.addEventListener("click", function(event) {
    let _target = event.target;
    this.handleClick(_target);
}.bind(this));

Inside we call a local method called handleClick() with the event’s target property. Nothing too exciting.

With Fat Arrow Functions, that becomes:

var listener = node.addEventListener("click", (event) => {
    let _target = event.target;
    this.handleClick(_target);
});

Look at all that saved typing!

The real benefit of course is that you don’t have to go through the mental hoop-jumping of trying to figure out what scope your function is going to run in (and more often-than-not, you just wanted it to run inside the current scope the function is being defined in anyway).

It just does the right thing.

Some interesting facts about Fat Arrow Functions

You can use them recursively. Because the containing scope closes over the fat arrow function, you can do things like,

let fib = (n) => {
    if (n <= 1) return 1;
    return fib(n - 1) + fib(n - 2);
}

You can’t use fat arrow functions as Generators. Deep continuations are not allowed. Fat Arrow functions are intended to be super light.

The “=>” syntax behaves like a “low-precedence assignment” operation. In

let x = () => { }

the order of operation is from left to right.

Update!

I didn’t include it originally, but some Fat Arrow Enthusiasts encouraged me to mention expression function syntax.

let square = (x) => { return x * x };

is equivalent to:

let square = x => x * x;

For single arguments, you can leave off the ()s. And for function expressions, you can lose the {}s and the return statement. Note that you cannot even use a return statement in this case as it’ll generate a syntax error about a missing semicolon. Don’t even try it!

22 thoughts on Fat Arrow Functions in JavaScript

  1. I think the main reason you can’t use fat arrow functions as generators is that they lack a lot of the scope machinery full-fledged functions have on them. They’re “lighter”.
    Continuations have to maintain a lot of extra state to work and would violate the simplicity of these constructs. Generators are expensive.

  2. nice article rob.quite enlightening. if i’m correct this means that the fat arrow functions do not replace the current function convention.

  3. Oh no, familiar function declarations will stick around. The world would break if that ever went away.

    Thanks for the comment!

  4. Sure. I didn’t say this was the only way or even the best way to add an event listener. Just mentioning a pattern that has cropped up.

    Also, using a handleEvent method in an object leads to a lot of:

    switch(event.type) cases if you need to trap multiple events.

    But this was about fat arrow functions…

  5. Pingback: Fat arrow functions in Javascript | Rocketboom

  6. Pingback: YUI Weekly for September 20th, 2013 - YUI Blog

  7. Is there any way to distinguish regular functions from fat arrow functions? It seems that, at invocation, it might be useful to know whether or not ‘this’ needs to be assigned.

  8. jon, this is currently available in Firefox 22 and up. As part of ES6, it should make it to V8 and IE sometime in the near future.

  9. tgwhite: that’s an interesting question. I bet you could use the fact that you can’t call “new” on a fat-arrow function to determine if it’s a regular function.

    typeof for both is “function”.

    Just for kicks:
    let isFatArrow = (functor) => {
    try {
    new functor();
    } catch(e) {
    return true;
    }
    return false;
    };

    function a() { return true };

    isFatArrow(isFatArrow); // true

    isFatArrow(a); // false

    works. (sorry for the crappy formatting)

  10. So, for the “let” statement to work, the code has to be placed in a script element with a type attribute that contains the “language” value, e.g. . On the other hand, arrow functions work in regular blocks. This should be noted in the article, since some people may try to test that code in their Firefox.

  11. that’s really an issue with jsFiddle, not Firefox. If you run your example code directly in a Scratchpad or the Console it will work.

  12. There is a slight error in your definition of fib

    let fib = (n) => {
    if (n <= 1) return 1;
    return fib(n – 1) + fib(n – 2};
    }

    You need to enclose n-2 in parentheses not a left parenthesis and a right curly brace.

Leave a Reply