Arrow Functions

Shorter syntax, lexical this, and the most common function style in modern JS.

Syntax

From verbose to concise — step by step.

// Traditional function:
function add(a, b) {
  return a + b;
}

// Arrow function (full form):
const add = (a, b) => {
  return a + b;
};

// Arrow function (concise):
const add = (a, b) => a + b;

Arrow functions replace the function keyword with =>. When there's a single expression, you can omit { } and return.

1 / 2

Implicit Return

Skip return and braces for single expressions.

// Concise body (implicit return):
const square = x => x * x;
const greet = name => `Hello, ${name}!`;
const isEven = n => n % 2 === 0;

// Block body (explicit return needed):
const process = (x) => {
  const doubled = x * 2;
  const formatted = `Result: ${doubled}`;
  return formatted;  // must use return!
};

// ⚠️ Returning an object literal — wrap in ():
const makeUser = (name) => ({ name, id: Date.now() });
//                          ^--- () needed! Otherwise { } = block

// Without (): 
const broken = (name) => { name, id: Date.now() };
// This is a block with a label, returns undefined!

// Common in array methods:
const names = users.map(u => u.name);
const adults = users.filter(u => u.age >= 18);
const total = prices.reduce((sum, p) => sum + p, 0);

Lexical this

Arrow functions don't have their own this — they inherit it.

// Regular function: 'this' depends on HOW it's called
const timer = {
  seconds: 0,
  start() {
    setInterval(function() {
      this.seconds++; // ❌ 'this' = window/undefined
      console.log(this.seconds); // NaN
    }, 1000);
  }
};

// Arrow function: 'this' is from WHERE it's defined
const timer = {
  seconds: 0,
  start() {
    setInterval(() => {
      this.seconds++; // ✓ 'this' = timer object
      console.log(this.seconds); // 1, 2, 3...
    }, 1000);
  }
};

Arrow functions capture 'this' from their enclosing scope at definition time. This is called lexical this.

1 / 2

Limitations

Things arrow functions can't do.

// ❌ No own 'this' — can't be used as methods:
const obj = {
  name: "Alice",
  greet: () => `Hi, I'm ${this.name}`, // 'this' = outer scope!
};
obj.greet(); // "Hi, I'm undefined"

// ✓ Use regular method syntax instead:
const obj = {
  name: "Alice",
  greet() { return `Hi, I'm ${this.name}`; }
};

// ❌ Can't be used as constructors:
const Person = (name) => { this.name = name; };
new Person("Alice"); // ❌ TypeError: not a constructor

// ❌ No 'arguments' object:
const fn = () => console.log(arguments); // ❌ ReferenceError
// Use rest params instead:
const fn = (...args) => console.log(args);

// ❌ Can't be generators:
const gen = *() => { yield 1; }; // ❌ SyntaxError

// ❌ No prototype property:
const arrow = () => {};
arrow.prototype; // undefined

When to Use

Arrow vs regular functions — a simple guide.

Use arrow functions for:

  • • Callbacks: arr.map(x => x * 2)
  • • Event handlers in classes/React
  • • Short utility functions
  • • Anywhere you need lexical this
  • • Promise chains: .then(data => ...)

Use regular functions for:

  • • Object methods: obj.method() {}
  • • Constructors: function Person() {}
  • • When you need arguments
  • • Generator functions
  • • DOM event handlers needing this = element

FAQ

Common questions about arrow functions.