This content originally appeared on DEV Community and was authored by JanetMutua
Introduction
Arrow functions were introduced in ECMAScript 2015 (ES6) and provide developers with a more concise syntax for writing anonymous function expressions. You can use them for short, one-liner functions instead of declaring a regular function.
Prerequisites
For this tutorial, you need a basic understanding of JavaScript concepts, like:
- Variables, functions, objects, and event handlers.
Let’s Get a Grasp of the Syntax First
When working with traditional function expressions, you assign an anonymous function to a variable that you can call later in your code. Arrow functions eliminate the need for using the function
keyword in expressions.
(Source: Gemini)
From the illustration above, the arrow function has no function keyword, curly braces, or return keyword. You eliminate curly braces and the return keyword in single expressions, but you will still need them if you are evaluating more expressions.
Take a look at how you write arrow functions in different scenarios:
// One parameter; multiple expressions
param => {
expression 1;
return expression 2;
}
// Single expression; multiple parameters
(param1, param2, ..., paramN) => expression
// Single expression; no parameters
() => expression
// Single expression; one parameter
param => param * 2;
Arrow Functions Use Cases
Arrow functions, being succinct and readable, are useful in various scenarios.
(Source: Gemini)
One such case is in declaring single-expression functions, where you can get away with an implicit return.
Take a look at the differences using an example of an exponential function. You can see the three-line regular function expression transform into only one line using an arrow function.
// Traditional function expression
const power = function (base, exponent) {
return base ** exponent;
};
// Arrow function
const power = (base, exponent) => base ** exponent;
Arrow functions are also useful when working with higher-order functions or array methods like map
, filter
, and reduce
. For instance, suppose you want to filter an array based on a certain criterion. How can you implement the logic using an arrow function?
// Given an array of user ages; filter for users younger than 35 years (youth)
const userAges = [23, 56, 34, 47, 18, 25, 90];
const youth = userAges.filter((age) => age <= 35);
console.log(youth);
// Output
// [23, 34, 18, 25]
With the filter
method, you pass an arrow function with the logic age <=35
that returns a new array with user ages equal to or below 35 years. The arrow function reduces boilerplate in cases where you need to manipulate large datasets.
Additionally, you can implement arrow functions in callbacks, especially with asynchronous operations or event handlers where preserving the ‘this‘ context is important.
Why Arrow Functions?
(Source: Gemini)
Apart from the rather obvious benefit of arrow functions being concise and readable, there are other benefits of arrow functions.
Arrow functions help solve the issue of losing the correct ‘this‘ binding when using traditional functions.
Arrow functions become beneficial in cases where the ‘this’ context can get lost. A good example is in code that involves callbacks, i.e., when working with event handlers or setTimeout
.
What does this actually mean?
One is that arrow functions avoid a common issue where ‘this‘ points to either a global object or undefined. Two, you no longer have to store ‘this’ in a variable (const self = this
) or use bind()
.
Let’s take a deeper look at the lexical ‘this
' binding.
Arrow Functions and the Lexical ‘This’ Binding
Arrow functions inherit ‘this
‘ from the surrounding context, like a function or block scope. That means that arrow functions don’t have their own ‘this’ value. Instead, the ‘this’ value is determined by the enclosing (lexical) scope.
(Source: Gemini)
To understand the lexical ‘this’ much better, let’s use an example of a function inside a block scope that takes the name of a person and logs it, then, after one second, logs the name again using setTimeout
.
// Example using a regular function
const person = {
name: "Julia the drummer",
introducePerson: function () {
console.log(`Hi! My name is ${this.name}`); // first output
setTimeout(function () {
console.log(`Actually my name is... ${this.name}`); // second output
}, 1000);
},
};
person.introducePerson();
// Output:
// Hi! My name is Julia the drummer
// Actually my name is... undefined
When you call person.introducePerson();
the first output that references ‘this
‘ returns the actual person’s name as expected. But inside setTimeout
, when a new function is called, the correct ‘this
‘ binding is lost, which is why we get undefined.
Now let’s see what happens when we replace the regular anonymous function in setTimeout
with an arrow function.
// Example using an arrow function
const person = {
name: "Julia the drummer",
introducePerson: function () {
console.log(`Hi! My name is ${this.name}`);
setTimeout(
() => console.log(`Actually my name is still... ${this.name}`),
1000
);
},
};
person.introducePerson();
// Output:
// Hi! My name is Julia the drummer
// Actually my name is still... Julia the drummer
As you can see, when using the arrow function, you retain the ‘this
‘ value of the original function.
Limitations of Arrow Functions
You can’t use arrow functions as constructors. That’s because you cannot override an arrow function with the new
keyword. One reason is that arrow functions don’t have their own ‘this
‘ binding, and two being that they lack the [[Construct]]
internal method needed for instantiation.
Additionally, you can’t use arrow functions as methods. That’s because arrow functions lack their own ‘this
’ binding along with arguments
or super
.
A Few Things To Keep in Mind
Arrow functions support destructuring, and also rest, and default parameters. Note that you always have to write these parameters in parentheses. Here’s a simple illustration of how:
// Default parameters
(a = 12, b = 6, c) => expression;
// Rest parameters
(a, b, ...r) => expression;
// Destructuring
// Array destructuring
([a, b]= [12, 6]) => expression;
// Object destructuring
({a, b} = {a: 12, b: 6}) => expression;
You can also make your arrow function asynchronous by prefixing it with the async
keyword just like this:
async param => expression;
Conclusion
In this article, you've learned:
- How arrow functions work, the inner workings of lexical ‘this‘ binding, and various use cases for arrow functions.
I hope this article has been of help to you.
Follow me on Hashnode and Medium for more tutorials and guides.
Keep building! 🌟
References
This content originally appeared on DEV Community and was authored by JanetMutua

JanetMutua | Sciencx (2025-08-26T13:12:58+00:00) Understanding Arrow Functions in JavaScript. Retrieved from https://www.scien.cx/2025/08/26/understanding-arrow-functions-in-javascript-2/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.