JavaScript arrow functions: syntax, this, and when not to use them
Every arrow function syntax form, how arrow functions take this from the surrounding code, what they cannot do, and the places a regular function or method is still the right choice.
Updated 6 min read

In this article
JavaScript arrow functions are shorter, but behaviour is the real difference. This guide covers every syntax form, how arrow function this comes from the surrounding code, what arrows cannot do and when to choose an arrow function vs regular function for methods, classes and DOM events.
An arrow function is a shorter way to write a function expression: (a, b) => a + b. The shorter syntax is the obvious difference, but the important one is behaviour: an arrow function has no this, arguments or prototype of its own and cannot be called with new. It uses the this of the code around it. That makes arrows ideal for callbacks and wrong for object methods, and most arrow-function bugs come from mixing those two up.
Tested with Node.js 24.19.0 (V8 13.6). Every result shown in a comment was printed by running the code; the same code runs in current Chrome, Firefox and Safari.
Arrow functions arrived in ES6 (ECMAScript 2015). They are used most as short callbacks, such as items.forEach((item) => console.log(item.name)) or prices.map((price) => price * 1.2), and as event handlers inside classes and components.
Arrow function syntax, every form
const add = (a, b) => a + b; // two parameters, implicit return
const double = n => n * 2; // one parameter: parentheses optional
const now = () => Date.now(); // no parameters: empty parentheses required
const area = ({ width, height }) => width * height; // destructured parameter
const greet = (name = 'there') => `Hello, ${name}`; // default value
const load = async (url) => (await fetch(url)).json(); // async arrow
const total = (items) => { // a block body needs an explicit return
const sum = items.reduce((acc, item) => acc + item.price, 0);
return Math.round(sum * 100) / 100;
};Two syntax rules catch people out:
- Returning an object literal needs parentheses. In
() => { id: 1 }the braces are read as a function body andid:as a label, so the function returnsundefined. Write() => ({ id: 1 }). - The arrow must be on the same line as the parameters. A line break between
(a, b)and=>is a syntax error; a line break after=>is fine.
How this works in an arrow function
A regular function gets its this from how it is called: obj.method() sets it to obj, a plain call leaves it undefined in strict code, and a timer or event callback gets whatever the caller passes. An arrow function ignores all of that and keeps the this of the function it was written in. This is called lexical this.
const counter = {
count: 0,
startRegular() {
setTimeout(function () {
console.log(this === counter); // false: a regular callback gets its own this
}, 0);
},
startArrow() {
setTimeout(() => {
this.count++;
console.log(this.count); // 1: the arrow uses start's this, the counter
}, 0);
},
};
counter.startRegular();
counter.startArrow();Before arrow functions this needed const self = this or .bind(this). Inside class methods, array callbacks, promise chains and timers, an arrow function is now the simplest correct choice.
Because the binding is fixed when the arrow is created, call, apply and bind cannot change an arrow's this: they still pass the arguments, but the first argument is ignored.
What arrow functions cannot do
const user = {
name: 'Asha',
greetArrow: () => `Hi ${this?.name}`,
greet() { return `Hi ${this.name}`; },
};
console.log(user.greetArrow()); // Hi undefined: this is the module's this, not user
console.log(user.greet()); // Hi Asha
const Point = (x, y) => ({ x, y });
try { new Point(1, 2); } catch (e) { console.log(e.constructor.name, e.message); } // TypeError Point is not a constructor
console.log(Point.prototype); // undefined
const sum = (...numbers) => numbers.reduce((total, n) => total + n, 0);
console.log(sum(1, 2, 3)); // 6
const wrong = () => { id: 1 };
const right = () => ({ id: 1 });
console.log(wrong(), right()); // undefined { id: 1 }- No own
this: an arrow written as an object property does not see the object. Use method shorthand,greet() { … }, for anything that readsthis. - No
arguments: use rest parameters,(...numbers), which give a real array. - No
newand noprototype: arrows cannot be constructors. Use a class. - No
superof their own and noyield: an arrow cannot be a generator.
Arrow functions in classes: fields versus methods
An arrow function assigned to a class field is created once per instance and keeps that instance as this, even when the function is passed around on its own. A normal method lives once on the prototype and loses this when it is detached:
class Timer {
seconds = 0;
tick = () => { this.seconds++; }; // a class field: bound to each instance
reset() { this.seconds = 0; } // a method: shared on the prototype
}
const timer = new Timer();
const { tick, reset } = timer;
tick();
console.log(timer.seconds); // 1
try { reset(); } catch (e) { console.log(e.constructor.name); } // TypeError: this is undefined
console.log(Object.hasOwn(timer, 'tick'), Object.hasOwn(timer, 'reset')); // true falseUse an arrow field for a function you will hand to someone else, such as an event listener you need to remove later with the same reference. Use normal methods for everything else: they are shared by all instances, appear on the prototype for subclasses to override with super, and cost less memory when you create many objects.
Arrow functions and DOM events
In a listener written as a regular function, this is the element the listener is attached to. In an arrow it is not, so read the element from the event instead, which works with both forms:
button.addEventListener('click', (event) => {
event.currentTarget.classList.toggle('is-active'); // the button, whatever this is
});When to use arrow functions, and when not to
| Situation | Use | Why |
|---|---|---|
Array callbacks: map, filter, reduce, sort | Arrow | Short, and no this needed |
| Callbacks inside a method: timers, promises, listeners | Arrow | Keeps the method's this |
Object methods that read this | Method shorthand | An arrow would not see the object |
| Class methods | Method | Shared on the prototype; overridable |
| A class callback passed elsewhere | Arrow field | Bound to the instance |
| Constructors and generators | Class or function* | Arrows cannot do either |
| Top-level named functions | Either | function declarations are hoisted; const arrows are not |
The last row is a style choice. A function declaration can be called before the line that defines it, while calling a const arrow early throws a ReferenceError. Many teams prefer declarations for named top-level functions because stack traces and reading order are clearer, and arrows for everything passed as a value.
Arrow functions in interviews
The most common interview questions here are what this is inside an arrow (the surrounding function's), why user.greetArrow() above prints undefined, and how to rewrite an arguments-based function with rest parameters. Our JavaScript interview questions and answers covers these alongside closures and the event loop.
Frequently asked questions
What is the difference between an arrow function and a regular function?
An arrow function has no
this,arguments,superorprototypeof its own: it uses thethisof the surrounding code and cannot be called withnewor be a generator. A regular function getsthisfrom how it is called.Why does my arrow function return undefined when I return an object?
In
() => { id: 1 }the braces are a function body, not an object. Wrap the object in parentheses:() => ({ id: 1 }).Can I use an arrow function as an object method?
Only if it never reads
this. An arrow written as an object property takesthisfrom the surrounding scope, not from the object, so use method shorthand such asgreet() { return this.name; }.Can bind, call or apply change this in an arrow function?
No. An arrow function's
thisis fixed when it is created.callandapplystill pass the other arguments, but thethisvalue you give them is ignored.
Your next customer could start right here.
Introduce your tool, product or business to readers exploring technology.
Explore placements and request a private quote
Sources
- Arrow function expressions — MDN Web Docs
- this — MDN Web Docs
- Public class fields — MDN Web Docs
- Rest parameters — MDN Web Docs
- ECMAScript 2025 Language Specification: Arrow Function Definitions — Ecma International TC39
Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.
Comments
No comments yet. Be the first to join the conversation.
Leave a comment
Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.
More from Cloudsoft Zone

Industry updateJavaScript
tsrs explained: can a Rust port make TypeScript checks 8x faster?
tsrs is an experimental Rust port of the TypeScript compiler from Cloudflare and VoidZero. What the 8x speed and 70% memory claims mean, and how to test it.
By Cloudsoft Zone

Troubleshooting guideDevOps
Laravel works locally, fails in production: trace runtime, configuration and request differences
Diagnose the Laravel works locally fails production problem by locating the first failing boundary: runtime, cached values, routing, permissions, dependencies or assets.
By Cloudsoft Zone

TutorialDevOps
Laravel log management: rotation, retention and safe production debugging
Set up Laravel log management with deliberate channels, retention, file ownership, rotation responsibility and useful incident context without recording secrets.
By Cloudsoft Zone
