Arrow functions, introduced in ES6, are a shorter syntax for writing function expressions. They're everywhere in modern JavaScript — callbacks, array methods, React components — because they cut out boilerplate and read cleanly for short, focused logic.
But arrow functions aren't just a shorthand for regular functions. They also behave differently when it comes to this, which makes them the right tool in some situations and the wrong one in others.
Basic Syntax
// Regular function expression
const addOld = function (a, b) {
return a + b;
};
// Arrow function, same behavior
const add = (a, b) => {
return a + b;
};
console.log(add(2, 3));
Output:
5
Implicit Return for One-Liners
When an arrow function's body is a single expression, you can drop the curly braces and the return keyword entirely — the result of the expression is returned automatically.
const square = x => x * x;
const greet = name => `Hello, ${name}!`;
console.log(square(6));
console.log(greet("Dev"));
// A single parameter can skip the parentheses (as above),
// but zero or multiple parameters always need them:
const sum = (a, b) => a + b;
const sayHi = () => "Hi!";
Output:
36
Hello, Dev!
This conciseness is exactly why arrow functions are the default choice inside array methods like map() and filter() — see them in action in the map, filter, and reduce tutorial.
The Key Difference: How Arrow Functions Handle `this`
This is the part that trips people up. A regular function gets its own this, determined by how it's called. An arrow function has no this of its own — it inherits this from the surrounding (lexical) scope where it was defined.
const counter = {
count: 0,
incrementRegular: function () {
setTimeout(function () {
// 'this' here is NOT counter — it's lost inside the callback
this.count++;
console.log(this.count); // NaN (this is undefined/global here)
}, 10);
},
incrementArrow: function () {
setTimeout(() => {
// Arrow function inherits 'this' from incrementArrow, which IS counter
this.count++;
console.log(this.count);
}, 10);
},
};
counter.incrementArrow(); // works as expected
Output:
1
This is why arrow functions are especially popular for callbacks (timers, promise handlers, array method callbacks) where you want this to still refer to the object the method was called on. The full rules for how this gets determined are covered separately, since it's a topic worth understanding on its own rather than squeezed into an arrow-function comparison.
When to Use a Regular Function Instead
Because arrow functions don't bind their own this, they're a poor fit for object methods that need to reference the object itself, and they can't be used as constructors with new. As a rule of thumb: use arrow functions for short callbacks and utility logic, and regular functions (or class methods) when this needs to refer to the calling object.
