What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?

There are no (significant) differences.

Well, okay, that’s a little premature. There are three tiny differences unique to arrow functions.

  1. Arrow functions cannot be used with new.

    This means, of course, that they do not have a prototype property and cannot be used to create an object with the classically-inspired syntax.

    new (() => {}) // TypeError: () => {} is not a constructor
    

    This is probably for the best, though—the way new works would not make much sense with bound functions.

  2. Arrow functions do not have access to the special arguments object that ordinary JavaScript functions have access to.

    (() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
    

    This one is probably a little bit more of a gotcha. Presumably this is to remove one of JavaScript’s other oddities. The arguments object is its own special beast, and it has strange behavior, so it’s not surprising that it was tossed.

    Instead, ES6 has splats that can accomplish the same thing without any magic hidden variables:

    ((...args) => args)(1, 2, 3) // [1, 2, 3]
    
  3. Arrow functions do not have their own new.target property, they use the new.target of their enclosing function, if it exists.

    This is consistent with the other changes to remove “magically” introduced values for arrow functions. This particular change is especially obvious, considering arrow functions can’t be used with new anyway, as mentioned above.

Otherwise, arrows are just like bound functions, semantically. It’s possible for arrows to be more performant, since they don’t have to carry around the extra baggage and since they don’t need to be converted from ordinary functions first, but they’re behaviorally exactly the same.

Leave a Comment