Arrow Functions
Introduction
Arrow functions are a concise ES6 syntax for function expressions. They are excellent for short callbacks and small transformations, but their most important semantic feature is not brevity: arrow functions have lexical this.
An arrow does not create its own this, arguments, super, or new.target. It closes over those values from the surrounding scope, which is powerful for nested callbacks and dangerous when you need a method with dynamic this.
Why This Matters
Arrow functions are everywhere in modern JavaScript and React code. Interviewers use them to separate syntax memorization from real understanding: concise return rules are easy, but lexical this, constructor limitations, and method pitfalls are the high-signal parts.
Theory
Syntax forms
- Expression body:
const double = n => n * 2;implicitly returns the expression. - Block body:
const double = n => { return n * 2; };needs an explicitreturn. - Multiple parameters require parentheses:
(a, b) => a + b. - Returning an object literal from an expression body requires parentheses:
() => ({ ok: true }).
Normal functions get this from how they are called: obj.method(), fn.call(value), new Fn(), and so on. Arrow functions skip that binding step. They read this from the closest surrounding non-arrow function or module scope.
The safest interview demonstration uses an explicit object method: a normal method receives this as the object, then returns an arrow that remembers that same object even when called later. Avoid examples that depend on the value of global this, because it differs across modules, browsers, workers, and strict mode.
Arrow functions cannot be constructors, so new Arrow() throws TypeError. They also do not have their own arguments object; use rest parameters instead. Because this is lexical, arrows are usually the wrong choice for object methods that expect obj.method() to set this. Use arrows for small callbacks, pure transformations, and nested functions that should inherit this.
Visual Diagrams
team.makeLabeler() normal method call sets this -> team method returns arrow arrow closes over team later labeler.call(other, 'Ada') call cannot replace arrow this arrow still reads team.prefix
An arrow's `this` is chosen where the arrow is created, not where it is called.
Code Examples
Arrow remembers the method receiver
The normal method gets this from team.makeLabeler(). The nested arrow captures that this and keeps it for later.
Use rest parameters instead of arguments
Arrows do not have their own arguments, so rest parameters are the explicit modern replacement.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1const profile = {2 name: 'Ada',3 makeArrowReader: function () {4 return () => this.name;5 },6 makeRegularReader: function () {7 return function () {8 return this.name;9 };10 }11};12 13const arrowReader = profile.makeArrowReader();14const regularReader = profile.makeRegularReader();15const other = { name: 'Grace' };16 17console.log(arrowReader.call(other));18console.log(regularReader.call(other));Coding Exercises
Build a prefix formatter with lexical this
MediumComplete makeFormatter on the formatter object so it returns a function. The returned function should format values as PREFIX:value, and it must keep using the original object even if the returned function is called with a different this.
Interview Questions
1What does it mean that arrow functions have lexical `this`?
An arrow does not bind its own this. It reads this from the surrounding scope where the arrow is created. Therefore .call, .apply, .bind, or method-call syntax cannot replace an arrow's this. This is useful for nested callbacks but wrong for methods that need dynamic receivers.
Follow-ups
- Can an arrow function be used with `new`?
- Why do arrows not have their own `arguments` object?
2When should you avoid arrow functions?
Avoid arrows for object methods that rely on this, constructor functions, generator functions, and wrappers that intentionally forward dynamic this. Use normal functions in those cases.
Quiz
1. Which statement about arrow functions is true?
Summary
- Arrow functions are concise function expressions introduced in ES6.
- Expression bodies implicitly return; block bodies require `return`.
- Arrows have lexical `this` and do not bind their own `arguments`.
- Use arrows for callbacks and inherited `this`; avoid them for dynamic methods and constructors.
Cheat Sheet
Forms: x => x * 2, (a, b) => a + b, () => ({ ok: true }).
Lexical this: chosen where the arrow is created; .call and .bind cannot replace it.
No own: this, arguments, super, new.target.
Cannot: be constructors or generators.
Use for: small callbacks, transformations, nested functions that should inherit this.