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.
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.
