Reader Stacks

What Are Arrow Functions in JavaScript (ES6)?

Arrow functions are shorter to write than function expressions, but the real difference that matters is how they handle this — they don't rebind it.

What Are Arrow Functions in JavaScript (ES6)?

Arrow functions, introduced in ES6, are more than a shorter syntax for writing functions — the genuinely important difference is how they handle this, which fixes a long-standing pain point with regular functions inside callbacks and class methods.

Basic syntax

// traditional function expression
const add = function (a, b) {
    return a + b;
};

// arrow function equivalent
const add = (a, b) => {
    return a + b;
};

// implicit return for a single expression
const add = (a, b) => a + b;

Single-parameter shorthand

const double = (x) => x * 2;
const double = x => x * 2; // parentheses are optional for exactly one parameter

The real difference: this binding

class Timer {
    constructor() {
        this.seconds = 0;
    }

    start() {
        // regular function: 'this' inside setInterval's callback is NOT the Timer instance
        setInterval(function () {
            this.seconds++; // this is undefined or the global object here, not the Timer
        }, 1000);
    }
}
class Timer {
    constructor() {
        this.seconds = 0;
    }

    start() {
        // arrow function: 'this' is inherited from the enclosing start() method
        setInterval(() => {
            this.seconds++; // this correctly refers to the Timer instance
        }, 1000);
    }
}

A regular function creates its own this binding based on how it's called — inside a callback like setInterval, that ends up being undefined (strict mode) or the global object, not the class instance you actually wanted. An arrow function has no this of its own; it inherits this lexically from the surrounding scope, which is exactly the instance you want inside a class method's callback.

Before arrow functions: the workarounds this replaced

// the .bind(this) workaround
setInterval(function () {
    this.seconds++;
}.bind(this), 1000);

// the "const self = this" workaround
const self = this;
setInterval(function () {
    self.seconds++;
}, 1000);

Arrow functions eliminate the need for either of these older patterns in the common case of wanting a callback that still refers to the enclosing object's this.

Arrow functions have no arguments object

function regular() {
    console.log(arguments); // works, array-like object of all passed arguments
}

const arrow = () => {
    console.log(arguments); // ReferenceError — arrow functions don't have their own arguments
};

Rest parameters ((...args) => ...) are the arrow-function-compatible replacement when you need access to all passed arguments.

When not to use an arrow function

Object methods that need this to refer to the object itself, and any function that needs to be used as a constructor (arrow functions can't be called with new), are the two common cases where a regular function is still the correct choice rather than an arrow function.