Open the console and click the buttons. Each section highlights one behavioral difference between
function declarations and arrow functions (=>).
this bindingRegular functions get their own this based on how they are called.
Arrow functions capture this from the enclosing scope.
const obj = {
name: "Widget",
regular: function () { return this; }, // `this` === obj
arrow: () => this, // `this` === outer scope (window)
};
this inside a callbackA classic bug: a regular function passed as a callback loses its this.
An arrow function inherits it from the surrounding method, so it just works.
class Counter {
constructor() { this.count = 0; }
startBroken() {
setInterval(function () { this.count++; }, 500); // `this` is window, not the Counter
}
startFixed() {
setInterval(() => { this.count++; }, 500); // `this` is the Counter
}
}
arguments objectRegular functions have a special arguments variable. Arrow functions
do not — referencing it either errors or falls through to an outer scope.
function regular() { return arguments.length; }
const arrow = () => arguments.length; // ReferenceError (in a module)
Regular functions can be called with new. Arrow functions cannot.
function Person(name) { this.name = name; }
const PersonArrow = (name) => { this.name = name; };
new Person("Ada"); // works
new PersonArrow("Ada"); // TypeError: PersonArrow is not a constructor
Function declarations are hoisted — you can call them before the line that defines them.
Arrow functions are assigned to variables, so they follow const/let rules.
hoisted(); // works
notHoisted(); // ReferenceError
function hoisted() { return "I'm up here early"; }
const notHoisted = () => "I'm only available after this line";