Array methods
Why it matters
In the previous topic we went through arrays with loops. It works, but the code gets long: create an
empty array, a loop, a condition, push… Arrays have methods that do typical things in one line:
"transform each element", "keep only the matching ones", "compute the total". Such code is shorter,
easier to read, and that's how JavaScript is written in real projects.
All these methods take a callback — a function called for each element. Usually it's an arrow function from topic 8.
forEach — do something with each
const names = ["Anna", "Timur", "Ira"];
names.forEach((name, index) => {
console.log(`${index + 1}. ${name}`);
});
Output:
1. Anna
2. Timur
3. Ira
The callback receives the element, its index and the array itself. forEach returns nothing — it's just a replacement for for.
map — transform each
map creates a new array of the same length from the callback's results:
const prices = [100, 250, 40];
const withTax = prices.map((p) => p * 1.2);
const labels = prices.map((p) => `${p} som`);
console.log(withTax);
console.log(labels);
console.log(prices);
Output:
[120,300,48]
["100 som","250 som","40 som"]
[100,250,40]
The original array doesn't change.
filter — keep the matching ones
filter returns a new array of only those elements for which the callback returned true:
const nums = [5, 12, 8, 130, 44];
console.log(nums.filter((n) => n > 10));
console.log(nums.filter((n) => n % 2 === 0));
Output:
[12,130,44]
[12,8,130,44]
find and findIndex — find the first
const users = [
{ name: "Anna", age: 15 },
{ name: "Timur", age: 19 },
{ name: "Ira", age: 21 },
];
console.log(users.find((u) => u.age >= 18));
console.log(users.findIndex((u) => u.age >= 18));
console.log(users.find((u) => u.age > 100));
Output:
{"name":"Timur","age":19}
1
undefined
(We'll cover objects like { name: …, age: … } in detail in the next topic. For now it's enough to know
that u.age is the value of the age field.)
some and every — checking
const ages = [15, 19, 21];
console.log(ages.some((a) => a < 18)); // true — at least one
console.log(ages.every((a) => a >= 18)); // false — all of them
reduce — fold into one value
reduce goes through the array and accumulates a result: a sum, a maximum, a string, an object.
const cart = [300, 150, 50];
const total = cart.reduce((sum, price) => sum + price, 0);
console.log(total);
Output:
500
The callback receives the "accumulator" (sum) and the current element and returns the new value of the
accumulator. The second argument of reduce (0) is the accumulator's starting value. Step by step:
0 + 300 = 300 → 300 + 150 = 450 → 450 + 50 = 500.
sort — sorting
const words = ["cherry", "apple", "banana"];
words.sort();
console.log(words);
const nums = [10, 9, 100, 1];
nums.sort();
console.log(nums); // surprise!
nums.sort((a, b) => a - b);
console.log(nums);
Output:
["apple","banana","cherry"]
[1,10,100,9]
[1,9,10,100]
Without a callback sort compares elements as strings, so "100" ends up before "9". For numbers
always pass a compare function: (a, b) => a - b — ascending, (a, b) => b - a — descending.
Important: sort (like reverse) changes the original array. To keep it, sort a copy: [...arr].sort(…).
Chains
Methods that return an array can be chained:
const orders = [120, 45, 300, 80, 15];
const bigTotal = orders
.filter((x) => x >= 50)
.map((x) => x * 0.9)
.reduce((s, x) => s + x, 0);
console.log(bigTotal);
Output:
450
It reads like a sentence: "take the orders of 50 and up, apply a 10% discount, add them up".
How it works inside
Inside, each method is an ordinary loop. map could be written like this:
function myMap(arr, fn) {
const result = [];
for (let i = 0; i < arr.length; i++) result.push(fn(arr[i], i, arr));
return result;
}
So methods aren't faster than loops — they're shorter and clearer. And sort with a callback asks at
each step: "a and b — who goes first?". A negative answer means a first, positive — b first, zero — equal.
Common mistakes
- No
returnin a callback with curly braces.arr.map((x) => { x * 2 })gives an array ofundefined. forEachinstead ofmap.forEachalways returnsundefined— it doesn't create a new array.- Sorting numbers without a function.
[10, 9, 1].sort()→[1, 10, 9]. You needsort((a, b) => a - b). sortspoiled the original array. Sort a copy:[...arr].sort(…).reducewithout a starting value. On an empty array it throws. Always pass the second argument.
Cheat sheet
| Method | What it does | Returns |
|---|---|---|
forEach(fn) |
calls fn for each | undefined |
map(fn) |
transforms each | a new array of the same length |
filter(fn) |
keeps where fn → true | a new array |
find(fn) / findIndex(fn) |
the first match | element / index (or undefined / -1) |
some(fn) / every(fn) |
at least one / all | true / false |
reduce(fn, start) |
folds into one | the final value |
sort((a, b) => a - b) |
sorts in place | the same array |