Arrow Functions in JavaScript: A Simpler Way to Write Functions
Less typing, cleaner syntax, and the modern way to write JavaScript functions. The first time I saw an arrow function, I thought someone had accidentally deleted half the code. No function keyword? No curly braces? No return statement? And it still works? const square = n => n * n; That's a complete, working function. It takes a number, squares it, and returns the result. Compare that to the traditional version: function square(n) { return n * n; } Same behavior, half the characters. Arrow functions were introduced in ES6 (2015), and they've become the default way to write functions in modern JavaScript. In the ChaiCode Web Dev Cohort 2026, they show up in almost every lesson — callbacks, array methods, event handlers, React components. If you're going to write modern JS, you need to be comfortable with them. Let's break it down step by step. An arrow function is a shorter, more concise syntax for writing function expressions. It uses the => (fat arrow) instead of the function keyword. That's really it. Arrow functions aren't some completely different concept — they're just a cleaner way to write the function expressions you already know. The => symbol looks like an arrow, which is why they're called "arrow functions." Some people also call them "fat arrow functions" because => uses the equals sign (fat) rather than a thin hyphen (->). Let me show you how a regular function transforms into an arrow function, step by step. This is the mental model that made it click for me. const greet = function(name) { return `Hello, ${name}!`; }; function Keyword, Add => const greet = (name) => { return `Hello, ${name}!`; }; {} and return const greet = (name) => `Hello, ${name}!`; const greet = name => `Hello, ${name}!`; Done. Four lines became one. Let's visualize that transformation: REGULAR FUNCTION: const greet = function(name) { ↑ ↑ keyword params return `Hello, ${name}!`; ↑ explicit return }; ⬇ Transform ⬇ ARROW FUNCTION: const greet = name => `Hello, ${name}!`; ↑ ↑ ↑ param arrow implicit return (no return keyword needed) When your function takes exactly one parameter, you can skip the parentheses around it. This is the shortest form of an arrow function. // With parentheses — works fine const double = (n) => n * 2; // Without parentheses — also works, slightly cleaner const double = n => n * 2; console.log(double(5)); // 10 console.log(double(12)); // 24 const shout = message => message.toUpperCase() + "!!!"; console.log(shout("hello")); // "HELLO!!!" const isPositive = num => num > 0; console.log(isPositive(5)); // true console.log(isPositive(-3)); // false const getLength = str => str.length; console.log(getLength("Pratham")); // 7 Each of these is a complete function — one parameter in, one value out. Clean and readable. When you have zero or more than one parameter, the parentheses are required. const sayHello = () => "Hello, World!"; console.log(sayHello()); // "Hello, World!" The () is mandatory here — you can't just write => "Hello, World!" with nothing before the arrow. const add = (a, b) => a + b; console.log(add(10, 5)); // 15 const fullName = (first, last) => `${first} ${last}`; console.log(fullName("Pratham", "Bhardwaj")); // "Pratham Bhardwaj" const max = (a, b) => a > b ? a : b; console.log(max(15, 22)); // 22 Parameters Parentheses Example Zero ✅ Required () => "hello" One ❌ Optional n => n * 2 or (n) => n * 2 Two or more ✅ Required (a, b) => a + b My personal preference: I always include parentheses even with one parameter. (n) => n * 2 is barely longer than n => n * 2, and it's consistent with the other cases. But both are valid — pick a style and stick with it. This is probably the thing that confuses beginners the most about arrow functions, so let me be very clear about it. {}, No return Keyword When the function body is a single expression, you can omit the curly braces and the return keyword. The result of the expression is automatically returned. // Implicit return — the expression after => is returned automatically const square = n => n * n; const greet = name => `Hello, ${name}!`; const isEven = n => n % 2 === 0; console.log(square(4)); // 16 console.log(greet("Pratham")); // "Hello, Pratham!" console.log(isEven(7)); // false No curly braces = implicit return. The arrow function evaluates the expression and gives it back. Simple. {} and return When the function body has multiple statements or you use curly braces for any reason, you must write return explicitly. Without it, the function returns undefined. // Explicit return — curly braces mean you MUST write return const calculateDiscount = (price, percentage) => { const discount = price * percentage / 100; const finalPrice = price - discount; return finalPrice; }; console.log(calculateDiscount(1000, 20)); // 800 return with Curly Braces This is a real bug that I've made more than once: // ❌ BUG — curly braces but no return const multiply = (a, b) => { a * b; // This computes the value but doesn't return it! }; console.log(multiply(3, 4)); // undefined 😱 // ✅ FIXED — add return const multiply = (a, b) => { return a * b; }; console.log(multiply(3, 4)); // 12 ✅ The rule is dead simple: No curly braces → result is returned automatically (implicit) Curly braces → you must write return yourself (explicit) IMPLICIT RETURN (single expression, no braces): const add = (a, b) => a + b; ↑ this value is returned automatically EXPLICIT RETURN (multiple statements, with braces): const add = (a, b) => { const sum = a + b; ← statement 1 return sum; ← you MUST return manually }; At a beginner level, here are the main differences you need to know: Feature Normal Function Arrow Function Syntax function name(params) {} (params) => {} function keyword ✅ Required ❌ Not used Implicit return ❌ Always needs return ✅ Yes, for single expressions Parentheses (1 param) ✅ Required ❌ Optional Hoisting ✅ Declarations are hoisted ❌ Not hoisted (they're expressions) Best for Standalone, named functions Callbacks, inline functions // Normal function declaration — hoisted, works before definition console.log(add(2, 3)); // 5 ✅ function add(a, b) { return a + b; } // Arrow function — NOT hoisted, fails before definition // console.log(multiply(2, 3)); // ❌ ReferenceError const multiply = (a, b) => a * b; console.log(multiply(2, 3)); // 6 ✅ — works after definition Arrow functions are always function expressions assigned to variables. And as we covered in a previous article, function expressions aren't hoisted. 💡 Note: Arrow functions also behave differently with this keyword compared to regular functions. That's an important topic, but it involves concepts like execution context and binding that go beyond beginner territory. For now, just know the difference exists — we'll tackle it when we're ready. Arrow functions truly shine when used as callbacks — functions passed as arguments to other functions. This is where you'll use them the most. map() — Transform Every Element const numbers = [1, 2, 3, 4, 5]; // Normal function const doubled1 = numbers.map(function(num) { return num * 2; }); // Arrow function — so much cleaner const doubled2 = numbers.map(num => num * 2); console.log(doubled2); // [2, 4, 6, 8, 10] filter() — Keep Only What Matches const ages = [15, 22, 17, 30, 12, 25]; const adults = ages.filter(age => age >= 18); console.log(adults); // [22, 30, 25] forEach() — Do Something with Each Element const fruits = ["Apple", "Mango", "Banana"]; fruits.forEach(fruit => console.log(`I like ${fruit}`)); // I like Apple // I like Mango // I like Banana setTimeout() — Delayed Execution setTimeout(() => { console.log("This runs after 2 seconds ⏰"); }, 2000); See how natural the arrow function looks as a callback? No function keyword cluttering things up, no unnecessary return. It's exactly why arrow functions became the modern standard for inline functions. // Normal function: square of a number function square(n) { return n * n; } console.log(square(5)); // 25 // Rewrite as arrow function const squareArrow = n => n * n; console.log(squareArrow(5)); // 25 const checkEvenOdd = n => n % 2 === 0 ? "Even" : "Odd"; console.log(checkEvenOdd(4)); // "Even" console.log(checkEvenOdd(7)); // "Odd" console.log(checkEvenOdd(0)); // "Even" console.log(checkEvenOdd(13)); // "Odd" map() const prices = [100, 250, 500, 1200, 3000]; // Add 18% GST to each price const withGST = prices.map(price => Math.round(price * 1.18)); console.log(withGST); // [118, 295, 590, 1416, 3540] // Format as currency strings const formatted = prices.map(price => `₹${price}`); console.log(formatted); // ["₹100", "₹250", "₹500", "₹1200", "₹3000"] // Convert each of these to arrow functions: // 1. Normal function greet(name) { return `Hello, ${name}!`; } // Arrow const greetArrow = name => `Hello, ${name}!`; // 2. Normal function getArea(length, width) { return length * width; } // Arrow const getAreaArrow = (length, width) => length * width; // 3. Normal function getCurrentYear() { return new Date().getFullYear(); } // Arrow const getCurrentYearArrow = () => new Date().getFullYear(); // Test them all console.log(greetArrow("Pratham")); // "Hello, Pratham!" console.log(getAreaArrow(10, 5)); // 50 console.log(getCurrentYearArrow()); // 2026 ┌─────────────────────────────────────────────────────────────────┐ │ ARROW FUNCTION ANATOMY │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ const functionName = (param1, param2) => expression; │ │ ↑ ↑ ↑ ↑ ↑ │ │ variable parameters fat arrow implicit return │ │ name (inputs) symbol (single expr) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ const functionName = (param1, param2) => { │ │ // multiple statements │ │ return result; ← explicit return required │ │ }; │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ SHORTHAND RULES: │ │ • 1 param → parentheses optional: n => n * 2 │ │ • 0 params → parentheses required: () => "hello" │ │ • 2+ params → parentheses required: (a, b) => a + b │ │ • 1 expression → braces optional: n => n * 2 (auto return) │ │ • 2+ statements → braces required: (n) => { ... return; } │ │ │ └─────────────────────────────────────────────────────────────────┘ Arrow functions are a shorter syntax for function expressions. They use => instead of the function keyword. With one parameter, parentheses are optional. With zero or multiple parameters, parentheses are required. Implicit return: if the body is a single expression (no curly braces), the result is returned automatically. Explicit return: if you use curly braces, you must write return. Arrow functions are not hoisted — you must define them before calling them, just like any function expression. They're the modern standard for callbacks and inline functions — map(), filter(), forEach(), setTimeout(), and beyond. Arrow functions felt like magic when I first saw them, but they're really just syntactic sugar — a shorter, cleaner way to write function expressions. The key is understanding when you can use implicit return (single expression, no braces) vs when you need explicit return (multiple statements, with braces). Once that clicks, you'll naturally reach for arrow syntax every time. I'm working through all of this in the ChaiCode Web Dev Cohort 2026 under Hitesh Chaudhary and Piyush Garg, and arrow functions are one of those things that show up in every single lesson now. Array methods, event handlers, React components — they all use arrow functions. Getting comfortable with them early pays off immediately. Connect with me on LinkedIn or visit PrathamDEV.in to follow my journey. More articles coming as I keep building and learning. Happy coding! 🚀 Written by Pratham Bhardwaj | Web Dev Cohort 2026, ChaiCode
