The javascript arrow function syntax (also called a javascript fat arrow or fat arrow function in javascript) uses => between parameters and body. It was standardized in ES2015 and is now the default style for short callbacks. This javascript arrow function tutorial covers concise bodies, when braces and return are required, js arrow function return object parentheses, lexical this, and what arrows cannot do (constructors, own arguments). For the legacy arguments object in normal functions, see JavaScript arguments; for ... in other contexts, see the spread operator in JavaScript.
Tested on: Node.js v20.18.2. A short note after each snippet describes what you should see in the console.
Quick reference
Arrows excel at lexical this and short callbacks; avoid them when you need dynamic this, new, or an arguments binding—use function or class fields instead.
| Situation | Prefer |
|---|---|
Short callback, no own this |
Arrow |
Object method needs this receiver |
Method shorthand m() { } or function property |
Need arguments binding |
function or (...args) => |
Need new |
function / class |
Block body — general arrow function in javascript
Use a block body when you need statements, local variables, or multiple steps before returning.
const power = (base, exponent) => {
let result = 1;
for (let count = 0; count < exponent; count++) {
result *= base;
}
return result;
};
console.log(power(2, 3));You should see one line like: 8.
Single parameter — optional parentheses (arrow function js)
With one simple parameter, parentheses are optional:
let square = (x) => x * x;
console.log(square(3));You should see one line like: 9.
Same meaning as x => x * x (no parens around x).
Zero or multiple parameters — parentheses required
Use () for zero parameters and (a, b) when there is more than one name (or for non-simple parameter lists).
const three = () => 3;
let add = (x, y) => x + y;
console.log(three(), add(3, 4));You should see one line like: 3 7.
Concise body vs block body
Expression body: omit { } and return; the expression is returned.
Block body: use { } and explicit return (unless you intentionally fall through to undefined).
let addAndMultiply = (x, y) => {
let sum = x + y;
let product = x * y;
return [sum, product];
};
console.log(addAndMultiply(3, 4));You should see one line like: [ 7, 12 ].
Returning an object literal — js arrow function return object
Braces after => start a block, not an object. Wrap the literal in ():
const objLit = () => ({ a: 1 });
console.log(objLit());You should see one line like: { a: 1 }.
Callbacks — javascript arrow function with map
Arrows are a natural fit for Array.prototype.map and similar APIs when you do not need a dynamic this. Pass a second parameter when you need the current index in the callback; see JavaScript map with index.
let numbers = [1, 2, 3, 4, 5];
let squares = numbers.map((x) => x * x);
console.log(squares);You should see one line like: [ 1, 4, 9, 16, 25 ].
Lexical this (strict + forEach)
In strict mode, a classic function passed to forEach gets undefined for this (unless you pass a thisArg). An arrow inherits this from the enclosing call:
(function () {
"use strict";
const greeter = {
prefix: "Hi ",
greet(names) {
names.forEach(function () {
console.log("classic", this === undefined ? "this:undefined" : this);
});
},
};
greeter.greet(["a"]);
})();
(function () {
"use strict";
const greeter = {
prefix: "Hi ",
greet(names) {
names.forEach((name) => console.log(this.prefix + name));
},
};
greeter.greet(["a", "b"]);
})();You should see 3 lines: classic this:undefined, then Hi a, then Hi b.
call / apply / bind do not change an arrow’s this:
const o = {
x: 2,
f: function () {
const arrow = () => this.x;
return arrow.call({ x: 99 });
},
};
console.log(o.f());You should see one line like: 2.
Not a constructor
Using new on an arrow throws because arrows have no [[Construct]] internal method.
try {
new (() => {});
} catch (e) {
console.log(`${e.name}: ${e.message}`);
}You should see one line like: TypeError: (intermediate value) is not a constructor.
Summary
=> trades features for brevity: no this, arguments, or new—wrap object literals in (), and use method shorthand when the receiver must bind dynamically.
=>gives compact syntax; expression bodies omitreturn, block bodies need explicitreturn.- Return object literals with
() => ({ ... })so{is not parsed as a block. - Lexical
thismakes arrows ideal for many callbacks but wrong for prototype methods that need the receiver. - Arrows are not constructors and have no own
arguments; usefunctionor rest parameters when those matter.
References
MDN documentation for arrow function expressions and dynamic this.
Frequently Asked Questions
What is the difference between arrow function javascript and a function declaration?
Arrow functions have a compact syntax, do not bind their own this, arguments, super, or new.target, and cannot be used as constructors. function declarations are hoisted and get a dynamic this when called as a method.
How do I js arrow function return object literals?
Wrap the object in parentheses: () => ({ key: 'value' }). Without parens, braces start a block body, not an object literal, so you get undefined or a label parse surprise.
Why is this wrong inside my arrow method on an object?
Arrows close over lexical this from where they were created, not the receiver. For methods that need the object (this), use a method shorthand greet() { ... } or a regular function property. Fluent APIs that chain with return this are covered in JavaScript chain functions.
Can I use new with an arrow function in javascript?
No. Arrow functions are not constructors and will throw TypeError when used with new.
Is there an arguments object in an arrow function?
Arrows do not have their own arguments binding. Use rest parameters (...args) or define a regular inner function if you need the classic arguments object; see also the guide on JavaScript arguments.
When must I use parentheses around arrow function parameters?
Use parens when there are zero parameters (), multiple parameters, or non-simple parameters such as defaults, rest, or destructuring. A single simple identifier can omit parens: x => x * x.
