JavaScript Arrow Functions
In this lesson
Arrow functions are a shorter way to write functions, added to JavaScript in 2015. You’ve already used them with map and filter. They’re everywhere in modern code, so it’s worth understanding them properly, including the one important way they behave differently.
From function to arrow#
The same function, written three ways:
// 1. Function declaration
function double(n) {
return n * 2;
}
// 2. Arrow function with a body
const double2 = (n) => {
return n * 2;
};
// 3. Arrow function with an implicit return
const double3 = n => n * 2;
console.log(double(5), double2(5), double3(5)); // 10 10 10
To turn a function into an arrow function:
- Remove the word
function. - Put
=>between the parameters and the body. - If the body is a single expression, remove the braces and
return: the value is returned automatically (implicit return).
Parameter rules#
const sayHi = () => "Hi!"; // no parameters: empty brackets required
const square = x => x * x; // one parameter: brackets optional
const add = (a, b) => a + b; // two or more: brackets required
const greet = (name = "friend") => `Hello, ${name}`; // defaults need brackets
console.log(sayHi(), square(4), add(2, 3), greet());
Many teams always use brackets, (x) => x * x, for consistency. Code formatters like Prettier do this by default.
When you need braces#
If the function needs more than one statement, use braces and an explicit return:
const priceWithTax = (price, rate = 0.18) => {
const tax = price * rate;
const total = price + tax;
return Math.round(total);
};
console.log(priceWithTax(1000)); // 1180
Watch out: with braces, nothing is returned unless you write return:
const broken = n => { n * 2 };
console.log(broken(5)); // undefined
Returning an object#
Braces after => are read as a function body, not an object. Wrap an object in brackets:
const makeUserWrong = name => { name: name }; // body with a label, returns undefined
const makeUser = name => ({ name, joined: Date.now() > 0 });
console.log(makeUserWrong("Asha")); // undefined
console.log(makeUser("Asha")); // { name: "Asha", joined: true }
Arrow functions as callbacks#
Arrow functions shine when passing small functions to other functions:
const scores = [72, 95, 41, 88, 60];
const passed = scores.filter(s => s >= 50);
const curved = scores.map(s => Math.min(s + 5, 100));
const best = scores.reduce((max, s) => (s > max ? s : max), 0);
const sorted = [...scores].sort((a, b) => b - a);
console.log(passed, curved, best, sorted);
Compare scores.filter(function (s) { return s >= 50; }): the arrow version is easier to read at a glance.
They’re also common with timers and events:
setTimeout(() => {
console.log("One second later…");
}, 1000);
The big difference: this#
Regular functions get their own this, which depends on how they’re called. Arrow functions **don’t have their own this**; they use the this of the code around them.
This makes arrow functions perfect inside methods:
const timer = {
seconds: 0,
start() {
const id = setInterval(() => {
this.seconds++; // "this" is still timer: correct
console.log(`${this.seconds}s`);
if (this.seconds === 3) clearInterval(id);
}, 300);
}
};
timer.start();
If you used function () { this.seconds++ } inside setInterval, this would not be the timer object and the code would break.
But it makes arrow functions a bad choice for methods themselves:
const user = {
name: "Rohan",
greetArrow: () => `Hi, I'm ${this?.name}`, // this is NOT user
greetMethod() { return `Hi, I'm ${this.name}`; } // this IS user
};
console.log(user.greetArrow()); // "Hi, I'm undefined"
console.log(user.greetMethod()); // "Hi, I'm Rohan"
Rule of thumb:
- Object methods → method shorthand
name() { … }. - Callbacks, small helpers, functions inside methods → arrow functions.
Other differences (less common)#
- Arrow functions can’t be used with
newto create objects. - They don’t have the old
argumentsobject; use rest parameters(...args)instead. - They aren’t hoisted: define them before you use them.
const logAll = (...args) => args.forEach(a => console.log(a));
logAll("one", "two", "three");
Readable arrow functions#
Short isn’t always clear. Name complex callbacks:
const orders = [
{ total: 1200, status: "paid" },
{ total: 300, status: "pending" },
{ total: 850, status: "paid" }
];
const isPaid = order => order.status === "paid";
const toTotal = order => order.total;
const sum = (a, b) => a + b;
const revenue = orders.filter(isPaid).map(toTotal).reduce(sum, 0);
console.log(revenue); // 2050
The last line now reads almost like a sentence.
Common mistakes#
- **Braces without
return** → the function returnsundefined. - Returning an object without wrapping brackets.
- Arrow functions as object methods, losing
this. - Overly clever one-liners that are hard to read.
Exercise#
- Rewrite
function triple(x) { return x * 3; }as an arrow function with an implicit return. - Write an arrow function
fullName(first, last)that returns a template string. - Write
toUser = name => ({ … })that returns an object with name andcreatedAt: new Date().toISOString(). - Given an array of words, use
filterandmapwith arrow functions to get the upper-case versions of words longer than 3 letters. - Create a
counterobject whosestart()method usessetIntervalwith an arrow function to count to 5.
Summary#
(params) => expressionreturns the expression automatically.- Use braces and
returnfor multi-line bodies; wrap returned objects in( ). - Arrow functions use the surrounding
this, which is ideal for callbacks inside methods. - Use method shorthand, not arrows, for object methods.
Next, you’ll learn about scope: where variables can be seen and used.
Quick quiz
3 questions. Check what stuck and earn 2 XP for each right answer.
Progress is saved in this browser. Create a free account to keep it on every device.
Get new lessons in your inbox
One email when we publish a new tutorial or guide. No spam, unsubscribe in one click.