Arrow Functions — ES6 Syntax
Arrow functions are a more concise syntax for writing functions. They were introduced in ES6 and have become the default choice for most JavaScript developers — but they have important differences from regular functions, especially regarding this.
// Regular function:
function add(a, b) {
return a + b;
}
// Arrow function — equivalent:
const add = (a, b) => {
return a + b;
};
// Concise body — implicit return when one expression:
const add = (a, b) => a + b;
// Single parameter — parentheses optional:
const double = n => n * 2;
const square = n => n ** 2;
// No parameters — empty parens required:
const greet = () => "Hello!";
const now = () => new Date();
// Returning an object — wrap in parentheses!
const makeUser = (name, age) => ({ name, age });
// Without parens, { would be interpreted as function body
// Multi-line still needs braces and return:
const processData = (data) => {
const filtered = data.filter(Boolean);
const doubled = filtered.map(n => n * 2);
return doubled;
};
Arrow Functions with Array Methods
const numbers = [1, 2, 3, 4, 5];
// Arrow functions shine with array methods:
const doubled = numbers.map(n => n * 2);
const odds = numbers.filter(n => n % 2 !== 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);
const firstBig = numbers.find(n => n > 3);
const hasZero = numbers.some(n => n === 0);
// Chaining:
const result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.filter(n => n % 2 === 0) // [2,4,6,8,10]
.map(n => n * n) // [4,16,36,64,100]
.filter(n => n < 50); // [4,16,36]
// Compare: with regular functions (verbose)
const doubled2 = numbers.map(function(n) { return n * 2; });
// vs arrow (clean):
const doubled3 = numbers.map(n => n * 2);
The this Keyword — Critical Difference
The most important difference between arrow functions and regular functions is how they handle this. Arrow functions don't have their own this — they inherit it from the surrounding scope.
// Regular function — 'this' depends on how the function is called
const obj = {
name: "Alice",
greet: function() {
console.log(`Hello, I'm ${this.name}`); // "Hello, I'm Alice"
}
};
obj.greet(); // 'this' = obj
// Arrow function — 'this' is inherited from outer scope
const obj2 = {
name: "Bob",
greet: () => {
console.log(`Hello, I'm ${this.name}`); // "Hello, I'm undefined"
// 'this' here is the outer scope (window/global), not obj2!
}
};
obj2.greet(); // Problem!
// This is why arrow functions are BAD for object methods
// but GREAT for callbacks inside methods:
const counter = {
count: 0,
start: function() {
// Arrow function inherits 'this' from start() method:
setInterval(() => {
this.count++; // 'this' correctly refers to counter
console.log(this.count);
}, 1000);
// Regular function would lose 'this':
// setInterval(function() {
// this.count++; // 'this' is window/undefined — BUG!
// }, 1000);
}
};
When to Use Each
| Use Case | Arrow Function | Regular Function |
|---|---|---|
| Array methods (map, filter) | ✓ Preferred | Works |
| Object methods | ✗ Avoid (this) | ✓ Use this |
| Callbacks | ✓ Preferred | Works |
| Constructors (new) | ✗ Cannot | ✓ Yes |
| Event handlers | Situational | ✓ If need this |
| Generators | ✗ Cannot | ✓ Yes |
⚡ Key Takeaways
- Arrow functions: shorter syntax, great for callbacks and array methods
- Implicit return: single-expression arrow functions return automatically
- Arrow functions have NO
this— they inherit from surrounding scope - Use regular functions for object methods that need to access the object via
this - Arrow functions cannot be used as constructors (
new) - Wrap returned objects in parentheses:
() => ({ key: value })
🎯 Practice Exercises
EXERCISE 1
Rewrite these regular functions as arrow functions with implicit returns: (1) function double(n) { return n*2; }, (2) function isEven(n) { return n%2===0; }, (3) a function that returns an object with name and age.
EXERCISE 2
Create an object timer with a count property and a start method. Inside start, use setTimeout with an arrow function to increment count after 1 second. Why does it work with arrow but not regular function?