Arrow Functions in JavaScript: A Simpler Way to Write Functions
Learn how JavaScript arrow functions work, from basic syntax to implicit returns. Beginner-friendly guide with practical examples.
Arrow functions are a cleaner, shorter way to write functions in JavaScript introduced in ES6. If you've been writing `function` keyword functions everywhere, this post will show you how to simplify your code without losing clarity.

Think of a regular function like filling out a full government form. You write your name, date, purpose, sign it, stamp it. Now think of an arrow function as a sticky note. Same information, way less paper. That's exactly what arrow functions do for your code: less ceremony, same result.
What Are Arrow Functions?
Arrow functions are an alternative syntax for writing functions in JavaScript. They were introduced in ES2015 (ES6) and have since become the default choice in modern JavaScript code. You'll see them everywhere: inside map(), filter(), event handlers, API calls, and more.
Here's the simplest way to understand it. Both of these do the exact same thing:
// Traditional function
function greet(name) {
return "Hello, " + name;
}
// Arrow function
const greet = (name) => {
return "Hello, " + name;
};The function keyword is gone. Instead, you get a => (which is literally an arrow, hence the name) sitting between the parameters and the function body.
For intermediate and advanced readers: arrow functions are not just syntax sugar. They behave differently from regular functions in a few key ways, but we'll get to the most important ones later. For now, focus on the syntax.
Breaking Down the Syntax
Let's look at the anatomy of an arrow function before going further:
┌─────────────────────────────────────────────────────────┐
│ Arrow Function Anatomy │
├─────────────────────────────────────────────────────────┤
│ │
│ const add = (a, b) => { return a + b; }; │
│ │ │ │ │ │ └──────┘│ │
│ │ │ │ │ │ body │ │
│ │ │ │ │ └─── arrow │ │
│ │ │ │ └────── params │ │
│ │ └──┘ │ │
│ │ parameters │ │
│ └── function name (via const) │ │
│ │ │
└─────────────────────────────────────────────────────────┘Arrow functions are always stored in variables (or passed directly as arguments). Unlike regular functions, they don't have their own name declaration. You give them a name by assigning them to a variable using const, let, or var.
One Parameter: Drop the Parentheses
When your arrow function takes exactly one parameter, you can skip the parentheses around it. This is purely optional, but a lot of developers prefer it for readability.
// With parentheses (always valid)
const double = (n) => {
return n * 2;
};
// Without parentheses (also valid, one param only)
const double = (n) => {
return n * 2;
};
console.log(double(5)); // 10Both are correct. Most style guides (like Airbnb's ESLint config) actually enforce keeping the parentheses even for single parameters, because it makes the code more consistent. Prettier does too. So don't stress too much about this one. Just know both forms exist when you read other people's code.
Multiple Parameters: Always Use Parentheses
Once you have two or more parameters, parentheses are not optional. They're required.
const add = (a, b) => {
return a + b;
};
const introduce = (firstName, lastName, age) => {
return firstName + " " + lastName + " is " + age + " years old.";
};
console.log(add(3, 7)); // 10
console.log(introduce("Atharv", "Dange", 22)); // Atharv Dange is 22 years old.Simple rule: zero params needs (), one param can skip (), two or more params requires ().
┌──────────────────────────────────────────────┐
│ Parameter Count Quick Reference │
├──────────────────────────────────────────────┤
│ │
│ 0 params → () => { ... } │
│ │
│ 1 param → name => { ... } │
│ OR │
│ (name) => { ... } │
│ │
│ 2+ params → (a, b) => { ... } │
│ │
└──────────────────────────────────────────────┘Implicit Return vs Explicit Return
This is where arrow functions get genuinely powerful, and where most beginners have an "aha" moment.
With a regular function (or a full arrow function body using {}), you always need to write return explicitly:
// Explicit return (you write return yourself)
const square = (n) => {
return n * n;
};But if your function body is a single expression, arrow functions let you skip both the curly braces {} and the return keyword. The expression's value is returned automatically. This is called an implicit return.
// Implicit return (return is implied)
const square = (n) => n * n;
console.log(square(4)); // 16Same result. Half the lines. Here's the rule: if you remove the {} curly braces, JavaScript treats whatever comes after the => as the return value. No need to write return.
Let's compare them side by side to make it crystal clear:
// Explicit return: curly braces + return keyword
const multiply = (a, b) => {
return a * b;
};
// Implicit return: no curly braces, no return keyword
const multiply = (a, b) => a * b;One edge case worth knowing: if you want to implicitly return an object literal, you need to wrap it in parentheses. Otherwise JavaScript thinks the {} is a function body, not an object.
// This looks like a function body to JS, returns undefined
const getUser = (name) => {
name: name;
};
// Wrap in parens to explicitly say "this is an object"
const getUser = (name) => ({ name: name });Advanced readers: this trips people up constantly. If you ever write an arrow function that returns an object and it keeps returning undefined, this is almost certainly why.
Arrow Function vs Regular Function: The Basics
The most visible difference is syntax. But there's one behavioral difference that matters even for beginners:
┌──────────────────────────────────────────────────────────────┐
│ Regular Function vs Arrow Function │
├──────────────────────────────────────────────────────────────┤
│ │
│ Regular Function Arrow Function │
│ ───────────────── ─────────────── │
│ │
│ function add(a, b) { const add = (a, b) => │
│ return a + b; a + b; │
│ } │
│ │
│ Has its own `this` Inherits `this` from │
│ context surrounding scope │
│ │
│ Can be used as a Cannot be used as a │
│ constructor (new) constructor │
│ │
│ Has `arguments` object No `arguments` object │
│ │
│ Hoisted to top of scope Not hoisted │
│ │
└──────────────────────────────────────────────────────────────┘For beginners right now, the hoisting difference is the most practical one. Regular functions declared with the function keyword get hoisted, meaning you can call them before they're defined in the file. Arrow functions (assigned to const or let) do not.
// This works (regular function is hoisted)
console.log(sayHi()); // "Hi!"
function sayHi() {
return "Hi!";
}
// This breaks (arrow function is not hoisted)
console.log(greet()); // ReferenceError
const greet = () => "Hello!";The this difference is a deeper topic that matters a lot when working with classes, event listeners, and object methods. It deserves its own post, so we're parking it for now.
The Transformation Pattern
The fastest way to get comfortable with arrow functions is to practice converting regular functions into arrow functions. Here's a visual breakdown of how that transformation looks:
┌─────────────────────────────────────────────────────────────┐
│ Regular → Arrow: Step by Step │
├─────────────────────────────────────────────────────────────┤
│ │
│ STEP 1: Start with regular function │
│ function square(n) { return n * n; } │
│ │
│ STEP 2: Assign to const, remove function keyword │
│ const square = (n) { return n * n; } │
│ │
│ STEP 3: Add the arrow => after parameters │
│ const square = (n) => { return n * n; } │
│ │
│ STEP 4 (optional): Use implicit return │
│ const square = (n) => n * n; │
│ │
└─────────────────────────────────────────────────────────────┘And here's a real-world use case that shows why arrow functions shine: callbacks inside array methods.
const numbers = [1, 2, 3, 4, 5];
// With regular function
const doubled = numbers.map(function (n) {
return n * 2;
});
// With arrow function (explicit return)
const doubled = numbers.map((n) => {
return n * 2;
});
// With arrow function (implicit return, cleanest)
const doubled = numbers.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]The third version is what you'll see in virtually every modern JavaScript codebase. Short, readable, no noise.
Try It Yourself
Here's a small set of exercises to lock in what you've learned. No frameworks, no build tools. Just open your browser console and type these out.
Exercise 1: Write a regular function that calculates the square of a number. Then convert it to an arrow function.
// Regular function version
function square(n) {
return n * n;
}
// Your arrow function version hereExercise 2: Write an arrow function that takes a number and returns whether it's even or odd as a string.
const isEvenOrOdd = (n) => (n % 2 === 0 ? "even" : "odd");
console.log(isEvenOrOdd(4)); // "even"
console.log(isEvenOrOdd(7)); // "odd"Exercise 3: Use an arrow function inside map() to double all values in an array.
const scores = [10, 20, 30, 40];
const doubled = scores.map((score) => score * 2);
console.log(doubled); // [20, 40, 60, 80]Key Takeaways
Arrow functions make your code cleaner and more readable, especially for short, single-purpose functions. Here's what to walk away with:
- Use
=>instead of thefunctionkeyword. - Zero or multiple params need
(), one param can skip them. - Drop the
{}andreturnfor single-expression functions, that's implicit return. - Arrow functions don't get hoisted, declare them before you use them.
- When returning an object implicitly, wrap it in
()to avoid bugs. - They're especially clean inside array methods like
map(),filter(), andreduce().
That's really it. Arrow functions aren't a replacement for regular functions in every case, but for callbacks, inline logic, and functional-style code, they're almost always the cleaner choice.