Arrow Functions in JavaScript: A Simpler Way to Write Functions

In our previous blogs, we learned about function declarations and expressions. Both of these approaches allow us to write reusable logic, preventing us from writing the same code over and over again.
But JavaScript is an evolving language. In 2015, a major update known as ES6 introduced a shorter, cleaner way to write functions. That new syntax is called Arrow Functions.
Today, we will look at how arrow functions work, how they simplify our code, and when you should use them.
What Are Arrow Functions?
Arrow functions were introduced in the ES6 (2015) specification of JavaScript. They provide a much shorter, more concise syntax for writing functions.
Unlike traditional function declarations, arrow functions are always written as expressions. This means they are typically assigned to a variable or passed directly into other functions as arguments. Because they reduce visual clutter, they have become the standard way to write functions in modern JavaScript development.
Let's look at a simple comparison to see how the boilerplate code is reduced
Normal function
function add(a, b) {
return a + b;
}
Arrow function
const add = (a, b) => {
return a + b;
};
By removing the function keyword and introducing the arrow operator (=>), we achieve the exact same functionality with a cleaner look.
Arrow Function Syntax Breakdown
To fully understand how to write an arrow function, let's break down the syntax step-by-step using a basic multiplication function.
const multiply = (a, b) => {
return a * b;
};
Here is exactly what is happening:
const multiply: We are declaring a variable namedmultiplyto store our function. You can also uselet, butconstis standard for functions so they cannot be accidentally overwritten.(a, b): These are the parameters (inputs). They are enclosed in parentheses, exactly like a normal function.=>: This is the arrow operator. It bridges the parameters to the body of the function, signaling to JavaScript that this is an arrow function.{ ... }: This is the function body, wrapped in curly braces. It holds the block of code that will execute.return: This keyword explicitly sends the final evaluated result back out of the function to wherever it was called.
Arrow Functions with One Parameter
Arrow functions include a special syntax rule to make your code even cleaner, if your function requires exactly one parameter, the parentheses around that parameter become optional.
const square = num => {
return num * num;
};
Dropping the parentheses around num reduces unnecessary syntax. This is highly practical and incredibly common in modern codebases when you are writing small, single-purpose functions.
Arrow Functions with Multiple Parameters
If your function requires two or more parameters or if it requires zero parameters at all
you must include the parentheses.
const subtract = (a, b) => {
return a - b;
};
const greet = () => "Hello"; // Parentheses are mandatory for zero parameters.
The parentheses are necessary here to clearly communicate to the JavaScript engine where the list of inputs begins and ends.
Implicit Return vs Explicit Return
Understanding how arrow functions handle return statements is one of the most important parts of mastering them. There are two ways an arrow function can return a value.
Explicit Return (Block Body) When you use curly braces {} to define the body of your arrow function, you are creating a block body. In a block body, you must use the return keyword to pass a value back.
const add = (a, b) => {
return a + b;
};
Implicit Return (Concise Body) If your function's logic is just a single expression (like a simple math calculation or a string combination), you can remove the curly braces entirely. When you do this, the return keyword is automatically implied.
const add = (a, b) => a + b;
This works perfectly for strings as well
const greet = name => "Hello " + name;
Important Note: If you choose to use curly braces, but you forget to write the word return, your function will output undefined. Implicit return only works when the curly braces are removed.
Basic Difference Between Arrow Function and Normal Function
While arrow functions might look like just a shorter way to write normal functions, they actually behave quite differently under the hood. Here are the primary differences you need to know as a beginner
They are always expressions: Arrow functions cannot be declared using the
functionkeyword. They must be defined as expressions and assigned to a variable or used inline.Shorter syntax: They remove the need for typing
functionand oftenreturn.No
thisbinding: Arrow functions do not have their ownthiscontext. They inherit it from the surrounding code. (We will explore this concept in depth later).const person = { name: "Purakhnath", greet: function() { console.log(this.name); // Works } }; const personArrow = { name: "Purakhnath", greet: () => { console.log(this.name); // undefined } };Why does this happen?
In a regular function, the value of
thisrefers to the object that is calling the function. So insideperson.greet(),thiscorrectly refers to thepersonobject.However, arrow functions do not create their own
this. Instead, they inheritthisfrom the surrounding (outer) scope at the time they are defined.In this example, the arrow function does not bind
thistopersonArrow. Instead, it uses the outer scope’sthis(which is usually the global object or undefined in strict mode), sothis.namebecomes undefined.Cannot be used as constructors: You cannot use the
newkeyword with an arrow function to create objects.Not hoisted: Like function expressions, arrow functions are not hoisted to the top of your file. You cannot call them before you define them.
No
argumentsobject: Regular functions have access to a specialargumentsobject that contains all passed arguments. Arrow functions do not have their ownargumentsobject.If you need to collect multiple arguments in an arrow function, you should use rest parameters instead.
// Regular function
function showArgs() {
console.log(arguments);
}
showArgs(1, 2, 3);
// Output: [1, 2, 3]
// Arrow function
const showArgsArrow = () => {
console.log(arguments);
};
showArgsArrow(1, 2, 3);
// ReferenceError: arguments is not defined
const showArgsArrow = (...args) => {
console.log(args);
};
showArgsArrow(1, 2, 3);
// Output: [1, 2, 3]
Visual Transformation Diagram
Here is a simple visualization of how a traditional function transforms into a concise arrow function
// Normal Function Expression
const add = function(a, b) {
return a + b;
};
//Replace "function" with arrow operator
//Arrow Function (Block Body)
const add = (a, b) => {
return a + b;
};
// Is the function body exactly ONE single expression?
// (No extra statements, no multiple lines)
// YES → Remove { } and return (implicit return)
const add = (a, b) => a + b;
// NO → Keep { } and use return
const addAndLog = (a, b) => {
console.log(a, b);
return a + b;
};
Practical Examples
Let's look at a few common, practical examples to see how readable arrow functions can be in everyday code.
Math Operations
const divide = (a, b) => a / b;
Checking if a number is even
const isEven = num => num % 2 === 0;
we dropped the parentheses for the single num parameter, and we used implicit return to immediately return true or false.
Using Arrow Function Inside map()
One of the most common places you will see arrow functions is acting as callbacks (functions passed into other functions). A perfect example of this is using array methods like map().
const numbers = [1, 2, 3, 4];
const squares = numbers.map(num => num * num);
console.log(squares);
// Output: [1, 4, 9, 16]
The map() method loops through every item in the numbers array. Instead of writing a bulky traditional function inside the parentheses, we pass a clean, one-line arrow function. It makes the data transformation logical, readable, and incredibly short.
Notes
Arrow functions are expressions.
They are not hoisted like function declarations.
Implicit return only works without curly braces.
They are best suited for short, clean functions.
Practice and Observation
To solidify your understanding, read through these four exercises. I highly encourage you to open your browser console or a code editor, type these out, and run them yourself.
Program 1: Write a normal function that calculates the square of a number.
function calculateSquare(num) {
return num * num;
}
console.log(calculateSquare(5)); // 25
This is the traditional way. It is perfectly valid, but it takes up three lines of code for a very simple mathematical operation.
Program 2: Rewrite the same logic using an arrow function.
const calculateSquareArrow = num => num * num;
console.log(calculateSquareArrow(5)); // 25
By utilizing the single-parameter rule and implicit return, we condensed three lines into a single, highly readable line.
Program 3: Create an arrow function that checks whether a number is even or odd.
const checkEvenOdd = num => num % 2 === 0 ? "Even" : "Odd";
console.log(checkEvenOdd(4)); // "Even"
console.log(checkEvenOdd(7)); // "Odd"
Arrow functions pair perfectly with the ternary operator (which we covered in our Control Flow blog) to make quick decisions without writing bulky if/else blocks.
Program 4: Use an arrow function inside map() to double the values of an array.
const prices = [10, 20, 30];
const doubledPrices = prices.map(price => price * 2);
console.log(doubledPrices); // [20, 40, 60]
This is the exact pattern you will use heavily when working with data arrays in modern JavaScript and libraries like React.
Notes
Forgetting
returninside{}: If you open a block with curly braces, JavaScript expects a manualreturn. If you forget it, the function returnsundefined.Calling before definition: Because they are variables holding expressions, they are not hoisted. Calling them too early throws an initialization error.
Confusing implicit return with object literals: If you want to implicitly return a JavaScript object, you must wrap the object in parentheses:
() => ({ name: "Purakhnath" }). Otherwise, JavaScript thinks the object's{}are the function's block boundaries.// Wrong (returns undefined) const getUser = () => { name: "Purakhnath" }; // Correct const getUser = () => ({ name: "Purakhnath" });Overusing arrow functions for everything: They are fantastic, but standard function declarations are still great for main program logic that you want hoisted to the top of your file.
Trying to use an arrow function as a constructor: They cannot be invoked with the
newkeyword.
Summary
Arrow functions simplify syntax and drastically reduce boilerplate code. They encourage a clean, modern style of writing JavaScript, especially when dealing with callbacks and array methods.
However, they still behave differently from normal functions. Understanding these structural differences like implicit returns and the lack of hoisting strengthens our ES6 fundamentals.
In the next blog, we will dive into JavaScript arrays and understand how to work with collections of data.




