Arrow Functions vs Regular Functions

Open the console and click the buttons. Each section highlights one behavioral difference between function declarations and arrow functions (=>).

1. this binding

Regular 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)
};

2. this inside a callback

A 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
  }
}

3. arguments object

Regular 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)

4. Constructors

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

5. Hoisting

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";