JavaScript 45 🧬 Array methods in depth
const nums = [1, 2, 3, 4, 5];
nums.map(n => n * 2);
nums.filter(n => n > 2);
nums.reduce((a, b) => a + b, 0);
nums.find(n => n > 3);
nums.findIndex(n => n > 3);
nums.some(n => n > 4);
nums.every(n => n > 0);
nums.includes(3);
nums.indexOf(4);
nums.slice(1, 3);
nums.concat([6, 7]);
nums.flat();
nums.flatMap(n => [n, n * 2]);
nums.sort((a, b) => a - b);
nums.reverse();
nums.join('-');
nums.forEach(n => console.log(n));
const arr = [3, 1, 2];
arr.push(4);
arr.pop();
arr.unshift(0);
arr.shift();
arr.splice(1, 2, 'x');
arr.fill(0);
arr.copyWithin(0, 2);
Array.from('abc');
Array.of(1, 2, 3);
Array.isArray([]);
Arrays come with dozens of built-in methods — the day-to-day tools that make JavaScript expressive. Some mutate the array in place; others return a new array or a value. Knowing which is which, and when to use what, is the difference between clean code and buggy code.
Key point: Every array method falls into one of four categories — mutating, non-mutating, iterating, or searching. The most common source of bugs is forgetting that methods like sort, reverse, splice, and push change the original array.
a – Iterating methods
These methods loop over an array and produce either a new array, a single value, or a side effect.
forEach — do something for each element:
const nums = [1, 2, 3];
nums.forEach(n => console.log(n));
// [ 1 ]
// [ 2 ]
// [ 3 ]
Returns undefined. Use it only for side effects — not for transforming.
map — transform each element:
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);
console.log(doubled);
// [ [ 2, 4, 6 ] ]
console.log(nums);
// [ [ 1, 2, 3 ] ] ← original unchanged
map returns a new array of the same length.
filter — keep elements that pass a test:
const nums = [1, 2, 3, 4, 5];
const evens = nums.filter(n => n % 2 === 0);
console.log(evens);
// [ [ 2, 4 ] ]
reduce — accumulate into a single value:
const nums = [1, 2, 3, 4];
const sum = nums.reduce((acc, n) => acc + n, 0);
console.log(sum);
// [ 10 ]
The second argument (0) is the initial accumulator. Without it, the first element is used:
const sum = nums.reduce((acc, n) => acc + n);
// [ 10 ]
reduce can build any value — arrays, objects, strings:
const words = ['a', 'b', 'c'];
const joined = words.reduce((acc, w) => acc + w, '');
console.log(joined);
// [ 'abc' ]
const counts = ['apple', 'banana', 'apple'].reduce((acc, w) => {
acc[w] = (acc[w] || 0) + 1;
return acc;
}, {});
console.log(counts);
// [ { apple: 2, banana: 1 } ]
reduceRight — reduce from the end:
const letters = ['a', 'b', 'c'];
const reversed = letters.reduceRight((acc, x) => acc + x, '');
console.log(reversed);
// [ 'cba' ]
flatMap — map then flatten one level:
const words = ['hello', 'world'];
const letters = words.flatMap(w => w.split(''));
console.log(letters);
// [ [ 'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd' ] ]
Comparison of iterating methods:
| Method | Returns | Purpose |
|---|---|---|
forEach | undefined | Side effects |
map | New array | Transform each |
filter | New array | Keep matching |
reduce | Any value | Accumulate |
reduceRight | Any value | Accumulate right-to-left |
flatMap | New array | Map + flatten |
b – Searching and testing methods
These methods look for specific elements or test a condition.
find — first match:
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const bob = users.find(u => u.id === 2);
console.log(bob);
// [ { id: 2, name: 'Bob' } ]
const missing = users.find(u => u.id === 99);
console.log(missing);
// [ undefined ]
Returns the first element matching, or undefined.
findIndex — index of first match:
const idx = users.findIndex(u => u.id === 2);
console.log(idx);
// [ 1 ]
const notFound = users.findIndex(u => u.id === 99);
console.log(notFound);
// [ -1 ]
findLast / findLastIndex — search from the end (ES2023):
const nums = [1, 2, 3, 4, 3, 2, 1];
console.log(nums.findLast(n => n > 2));
// [ 3 ]
console.log(nums.findLastIndex(n => n > 2));
// [ 4 ]
some — is there at least one match?
const nums = [1, 2, 3];
console.log(nums.some(n => n > 2));
// [ true ]
console.log(nums.some(n => n > 10));
// [ false ]
every — do all match?
const nums = [2, 4, 6];
console.log(nums.every(n => n % 2 === 0));
// [ true ]
console.log(nums.every(n => n > 3));
// [ false ]
includes — does the array contain a value?
const fruits = ['apple', 'banana'];
console.log(fruits.includes('banana'));
// [ true ]
console.log(fruits.includes('cherry'));
// [ false ]
console.log([1, 2, 3].includes(2));
// [ true ]
console.log([NaN].includes(NaN));
// [ true ] ← unlike indexOf
indexOf / lastIndexOf — find the index of a value:
const nums = [1, 2, 3, 2, 1];
console.log(nums.indexOf(2));
// [ 1 ]
console.log(nums.lastIndexOf(2));
// [ 3 ]
console.log(nums.indexOf(99));
// [ -1 ]
indexOf uses strict equality — NaN won’t be found (use includes instead).
Comparison of search methods:
| Method | Returns | Use for |
|---|---|---|
find | Element or undefined | Complex objects |
findIndex | Index or -1 | Complex objects |
findLast | Element or undefined | Search from end |
findLastIndex | Index or -1 | Search from end |
some | Boolean | Any match |
every | Boolean | All match |
includes | Boolean | Primitive value |
indexOf | Index or -1 | Primitive value |
lastIndexOf | Index or -1 | Last occurrence |
Rules of thumb:
- Use
findfor objects —indexOfuses===and won’t match object references - Use
includesforNaN—indexOf(NaN)returns-1 - Use
somefor “any” andeveryfor “all” - Use
findIndexwhen you need the index
c – Mutating methods
These methods change the original array. Use them with care.
push — add to end:
const arr = [1, 2];
arr.push(3);
console.log(arr);
// [ [ 1, 2, 3 ] ]
arr.push(4, 5);
console.log(arr);
// [ [ 1, 2, 3, 4, 5 ] ]
Returns the new length.
pop — remove from end:
const arr = [1, 2, 3];
const last = arr.pop();
console.log(last);
// [ 3 ]
console.log(arr);
// [ [ 1, 2 ] ]
Returns the removed element.
unshift — add to start:
const arr = [2, 3];
arr.unshift(1);
console.log(arr);
// [ [ 1, 2, 3 ] ]
Returns the new length.
shift — remove from start:
const arr = [1, 2, 3];
const first = arr.shift();
console.log(first);
// [ 1 ]
console.log(arr);
// [ [ 2, 3 ] ]
Returns the removed element.
splice — add, remove, or replace anywhere:
const arr = [1, 2, 3, 4, 5];
// Remove 2 elements starting at index 1
arr.splice(1, 2);
console.log(arr);
// [ [ 1, 4, 5 ] ]
const arr = [1, 2, 3, 4, 5];
// Replace 2 elements starting at index 1 with 'a', 'b'
arr.splice(1, 2, 'a', 'b');
console.log(arr);
// [ [ 1, 'a', 'b', 4, 5 ] ]
const arr = [1, 2, 3];
// Insert without removing
arr.splice(1, 0, 'x');
console.log(arr);
// [ [ 1, 'x', 2, 3 ] ]
Returns an array of removed elements.
sort — sort in place:
const nums = [3, 1, 4, 1, 5];
nums.sort();
console.log(nums);
// [ [ 1, 1, 3, 4, 5 ] ]
Default sort is lexicographic — converts to strings:
const nums = [10, 2, 33, 4];
nums.sort();
console.log(nums);
// [ [ 10, 2, 33, 4 ] ] ← ❌ wrong
nums.sort((a, b) => a - b);
console.log(nums);
// [ [ 2, 4, 10, 33 ] ] ← ✅ numeric
Numeric sort comparators:
arr.sort((a, b) => a - b); // ascending
arr.sort((a, b) => b - a); // descending
String sort with locale:
const names = ['Zoë', 'anna', 'Bob'];
names.sort((a, b) => a.localeCompare(b));
console.log(names);
// [ [ 'anna', 'Bob', 'Zoë' ] ]
reverse — reverse in place:
const arr = [1, 2, 3];
arr.reverse();
console.log(arr);
// [ [ 3, 2, 1 ] ]
fill — fill with a value:
const arr = [1, 2, 3, 4];
arr.fill(0);
console.log(arr);
// [ [ 0, 0, 0, 0 ] ]
const arr2 = [1, 2, 3, 4];
arr2.fill(0, 1, 3);
console.log(arr2);
// [ [ 1, 0, 0, 4 ] ]
copyWithin — copy part of the array to another position:
const arr = [1, 2, 3, 4, 5];
arr.copyWithin(0, 3);
console.log(arr);
// [ [ 4, 5, 3, 4, 5 ] ]
Comparison of mutating methods:
| Method | Effect | Returns |
|---|---|---|
push | Add to end | New length |
pop | Remove from end | Removed item |
unshift | Add to start | New length |
shift | Remove from start | Removed item |
splice | Add/remove/replace | Removed items |
sort | Sort in place | The array |
reverse | Reverse in place | The array |
fill | Fill values | The array |
copyWithin | Copy internally | The array |
Which methods mutate:
| Method | Mutates? |
|---|---|
push / pop | ✅ |
shift / unshift | ✅ |
splice | ✅ |
sort | ✅ |
reverse | ✅ |
fill | ✅ |
copyWithin | ✅ |
map / filter | ❌ |
slice / concat | ❌ |
flat / flatMap | ❌ |
toSorted / toReversed | ❌ |
toSpliced / with | ❌ |
Copy-before-mutate pattern:
const original = [3, 1, 2];
const sorted = [...original].sort((a, b) => a - b);
console.log(original);
// [ [ 3, 1, 2 ] ] ← unchanged
console.log(sorted);
// [ [ 1, 2, 3 ] ]
ES2023 non-mutating variants:
const original = [3, 1, 2];
const sorted = original.toSorted((a, b) => a - b);
const reversed = original.toReversed();
const spliced = original.toSpliced(1, 1);
const replaced = original.with(1, 99);
console.log(original);
// [ [ 3, 1, 2 ] ] ← unchanged
Modern code should prefer the non-mutating versions.
d – Non-mutating methods
These methods return new arrays or values without changing the original.
slice — extract a portion:
const arr = [1, 2, 3, 4, 5];
console.log(arr.slice(1, 3));
// [ [ 2, 3 ] ]
console.log(arr.slice(2));
// [ [ 3, 4, 5 ] ]
console.log(arr.slice(-2));
// [ [ 4, 5 ] ]
console.log(arr.slice());
// [ [ 1, 2, 3, 4, 5 ] ] ← shallow copy
concat — combine arrays:
const a = [1, 2];
const b = [3, 4];
console.log(a.concat(b));
// [ [ 1, 2, 3, 4 ] ]
console.log([].concat(a, b, 5));
// [ [ 1, 2, 3, 4, 5 ] ]
flat — flatten nested arrays:
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat());
// [ [ 1, 2, 3, 4, [ 5, 6 ] ] ]
console.log(nested.flat(2));
// [ [ 1, 2, 3, 4, 5, 6 ] ]
console.log(nested.flat(Infinity));
// [ [ 1, 2, 3, 4, 5, 6 ] ]
join — turn into a string:
const arr = ['a', 'b', 'c'];
console.log(arr.join());
// [ 'a,b,c' ]
console.log(arr.join('-'));
// [ 'a-b-c' ]
console.log(arr.join(''));
// [ 'abc' ]
at — access by index (supports negative):
const arr = [10, 20, 30];
console.log(arr.at(0));
// [ 10 ]
console.log(arr.at(-1));
// [ 30 ]
console.log(arr[-1]);
// [ undefined ] ← doesn't work with brackets
toString — default string conversion:
const arr = [1, 2, 3];
console.log(arr.toString());
// [ '1,2,3' ]
Comparison of non-mutating methods:
| Method | Returns | Purpose |
|---|---|---|
slice | New array | Extract portion |
concat | New array | Combine |
flat | New array | Flatten nested |
flatMap | New array | Map + flatten |
join | String | Join elements |
at | Element | Access by index |
toString | String | Default string |
toSorted | New array | Sorted copy |
toReversed | New array | Reversed copy |
toSpliced | New array | Spliced copy |
with | New array | Replaced element |
Complete Example Session
// ============================================
// PART 1: MAP
// ============================================
const nums = [1, 2, 3, 4, 5];
console.log(nums.map(n => n * 2));
// [ [ 2, 4, 6, 8, 10 ] ]
// ============================================
// PART 2: FILTER
// ============================================
console.log(nums.filter(n => n > 2));
// [ [ 3, 4, 5 ] ]
// ============================================
// PART 3: REDUCE
// ============================================
console.log(nums.reduce((a, b) => a + b, 0));
// [ 15 ]
// ============================================
// PART 4: FIND
// ============================================
console.log(nums.find(n => n > 3));
// [ 4 ]
console.log(nums.find(n => n > 10));
// [ undefined ]
// ============================================
// PART 5: FINDINDEX
// ============================================
console.log(nums.findIndex(n => n > 3));
// [ 3 ]
// ============================================
// PART 6: SOME / EVERY
// ============================================
console.log(nums.some(n => n > 4));
// [ true ]
console.log(nums.every(n => n > 0));
// [ true ]
// ============================================
// PART 7: INCLUDES / INDEXOF
// ============================================
console.log(nums.includes(3));
// [ true ]
console.log(nums.indexOf(4));
// [ 3 ]
console.log([NaN].includes(NaN));
// [ true ]
console.log([NaN].indexOf(NaN));
// [ -1 ]
// ============================================
// PART 8: SLICE / CONCAT
// ============================================
console.log(nums.slice(1, 3));
// [ [ 2, 3 ] ]
console.log(nums.concat([6, 7]));
// [ [ 1, 2, 3, 4, 5, 6, 7 ] ]
// ============================================
// PART 9: FLAT / FLATMAP
// ============================================
console.log([1, [2, [3]]].flat(2));
// [ [ 1, 2, 3 ] ]
console.log(['hello', 'world'].flatMap(w => w.split('')));
// [ [ 'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd' ] ]
// ============================================
// PART 10: SORT
// ============================================
const nums2 = [10, 2, 33, 4];
console.log([...nums2].sort());
// [ [ 10, 2, 33, 4 ] ] ← lexicographic
console.log([...nums2].sort((a, b) => a - b));
// [ [ 2, 4, 10, 33 ] ]
// ============================================
// PART 11: REVERSE
// ============================================
console.log([...nums].reverse());
// [ [ 5, 4, 3, 2, 1 ] ]
// ============================================
// PART 12: JOIN
// ============================================
console.log(nums.join('-'));
// [ '1-2-3-4-5' ]
// ============================================
// PART 13: MUTATING — PUSH / POP
// ============================================
const arr1 = [1, 2];
arr1.push(3);
console.log(arr1);
// [ [ 1, 2, 3 ] ]
arr1.pop();
console.log(arr1);
// [ [ 1, 2 ] ]
// ============================================
// PART 14: MUTATING — SPLICE
// ============================================
const arr2 = [1, 2, 3, 4, 5];
arr2.splice(1, 2, 'a', 'b');
console.log(arr2);
// [ [ 1, 'a', 'b', 4, 5 ] ]
// ============================================
// PART 15: NON-MUTATING ES2023
// ============================================
const original = [3, 1, 2];
const sorted = original.toSorted((a, b) => a - b);
console.log(sorted);
// [ [ 1, 2, 3 ] ]
console.log(original);
// [ [ 3, 1, 2 ] ]
// ============================================
// PART 16: REDUCE TO OBJECT
// ============================================
const words = ['apple', 'banana', 'apple'];
const counts = words.reduce((acc, w) => {
acc[w] = (acc[w] || 0) + 1;
return acc;
}, {});
console.log(counts);
// [ { apple: 2, banana: 1 } ]
// ============================================
// PART 17: CHAINING
// ============================================
const result = nums
.filter(n => n % 2 === 0)
.map(n => n * 10)
.reduce((a, b) => a + b, 0);
console.log(result);
// [ 60 ]
// ============================================
// PART 18: GROUP BY (MANUAL)
// ============================================
const people = [
{ name: 'Alice', dept: 'Eng' },
{ name: 'Bob', dept: 'Sales' },
{ name: 'Charlie', dept: 'Eng' }
];
const byDept = people.reduce((acc, p) => {
(acc[p.dept] ||= []).push(p.name);
return acc;
}, {});
console.log(byDept);
// [ { Eng: [ 'Alice', 'Charlie' ], Sales: [ 'Bob' ] } ]
// ============================================
// PART 19: ARRAY STATIC METHODS
// ============================================
console.log(Array.from('abc'));
// [ [ 'a', 'b', 'c' ] ]
console.log(Array.from({ length: 3 }, (_, i) => i));
// [ [ 0, 1, 2 ] ]
console.log(Array.of(1, 2, 3));
// [ [ 1, 2, 3 ] ]
console.log(Array.isArray([]));
// [ true ]
// ============================================
// PART 20: FULL SCRIPT
// ============================================
const nums45 = [1, 2, 3, 4, 5];
nums45.map(n => n * 2);
nums45.filter(n => n > 2);
nums45.reduce((a, b) => a + b, 0);
nums45.find(n => n > 3);
nums45.findIndex(n => n > 3);
nums45.some(n => n > 4);
nums45.every(n => n > 0);
nums45.includes(3);
nums45.indexOf(4);
nums45.slice(1, 3);
nums45.concat([6, 7]);
nums45.flat();
nums45.flatMap(n => [n, n * 2]);
nums45.sort((a, b) => a - b);
nums45.reverse();
nums45.join('-');
nums45.forEach(n => console.log(n));
const arr45 = [3, 1, 2];
arr45.push(4);
arr45.pop();
arr45.unshift(0);
arr45.shift();
arr45.splice(1, 2, 'x');
arr45.fill(0);
arr45.copyWithin(0, 2);
Array.from('abc');
Array.of(1, 2, 3);
Array.isArray([]);
Quick Reference
Iterating Methods
| Method | Returns | Mutates? |
|---|---|---|
forEach | undefined | ❌ |
map | New array | ❌ |
filter | New array | ❌ |
reduce | Any value | ❌ |
reduceRight | Any value | ❌ |
flatMap | New array | ❌ |
Searching Methods
| Method | Returns | For |
|---|---|---|
find | Element / undefined | Objects |
findIndex | Index / -1 | Objects |
findLast | Element / undefined | From end |
findLastIndex | Index / -1 | From end |
some | Boolean | Any |
every | Boolean | All |
includes | Boolean | Primitives, NaN |
indexOf | Index / -1 | Primitives |
lastIndexOf | Index / -1 | Last |
Mutating Methods
| Method | Effect |
|---|---|
push | Add end |
pop | Remove end |
unshift | Add start |
shift | Remove start |
splice | Add/remove anywhere |
sort | Sort in place |
reverse | Reverse in place |
fill | Fill values |
copyWithin | Copy internally |
Non-Mutating Methods
| Method | Returns |
|---|---|
slice | New array |
concat | New array |
flat | New array |
flatMap | New array |
join | String |
at | Element |
toSorted | New array (ES2023) |
toReversed | New array (ES2023) |
toSpliced | New array (ES2023) |
with | New array (ES2023) |
Static Methods
| Method | Purpose |
|---|---|
Array.from(iterable) | Array from iterable |
Array.from({length}, fn) | Generate |
Array.of(a, b, c) | Create from args |
Array.isArray(x) | Check array |
Sort Comparators
| Sort | Comparator |
|---|---|
| Numeric ascending | (a, b) => a - b |
| Numeric descending | (a, b) => b - a |
| String | (a, b) => a.localeCompare(b) |
| By property | (a, b) => a.x - b.x |
reduce Patterns
| Pattern | Code |
|---|---|
| Sum | .reduce((a, b) => a + b, 0) |
| Max | .reduce((a, b) => a > b ? a : b) |
| Count | .reduce((acc, x) => (acc[x] = (acc[x] || 0) + 1, acc), {}) |
| Group | .reduce((acc, x) => ((acc[x.k] ||= []).push(x), acc), {}) |
| Flatten | .reduce((a, b) => a.concat(b), []) |
Best Practices
✅ Do This:
// Use map for transform, filter for selection
nums.map(n => n * 2); // ✅
nums.filter(n => n > 0); // ✅
// Use find for objects
users.find(u => u.id === 1); // ✅
// Use includes for NaN
[NaN].includes(NaN); // ✅
// Use numeric sort comparator
nums.sort((a, b) => a - b); // ✅
// Copy before mutating
const sorted = [...arr].sort(); // ✅
const sorted = arr.toSorted(); // ✅
// Chain for readable pipelines
arr.filter(...).map(...).reduce(...); // ✅
// Use reduce to build objects
.reduce((acc, x) => (acc[x] = 1, acc), {}); // ✅
// Use Array.from for array-likes
Array.from('hello'); // ✅
Array.from({length: 5}, (_, i) => i); // ✅
❌ Don’t Do This:
// Don't use forEach to transform
arr.forEach(n => n * 2); // ❌ use map
// Don't use map for side effects
arr.map(n => console.log(n)); // ❌ use forEach
// Don't use indexOf for NaN
[NaN].indexOf(NaN); // ❌ returns -1
// Don't forget sort mutates
const sorted = arr.sort(); // ⚠️ changes arr
const sorted = [...arr].sort(); // ✅
// Don't sort numbers without comparator
[10, 2, 33].sort(); // ❌ lexicographic
// Don't use find to get index
users.find(u => u.id === 1); // ⚠️ use findIndex
// Don't reduce without initial for empty arrays
[].reduce((a, b) => a + b); // ❌ TypeError
[].reduce((a, b) => a + b, 0); // ✅
// Don't use splice when slice works
arr.splice(0, arr.length); // ⚠️ mutates
arr.slice(); // ✅ returns copy
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
sort mutates | Original changed | [...arr].sort() or toSorted |
| No sort comparator | Lexicographic | (a, b) => a - b |
indexOf(NaN) | Returns -1 | Use includes |
find on object identity | Fails for different refs | Compare properties |
Empty reduce | TypeError | Provide initial value |
forEach return | Ignored | Use map |
map for side effects | Wastes memory | Use forEach |
Forgetting flat depth | Returns nested | flat(Infinity) |
Real-World Examples
1. Transform with map
const prices = [10, 20, 30];
const withTax = prices.map(p => p * 1.2);
console.log(withTax);
// [ [ 12, 24, 36 ] ]
2. Filter active users
const users = [
{ name: 'Alice', active: true },
{ name: 'Bob', active: false }
];
const active = users.filter(u => u.active);
console.log(active);
// [ [ { name: 'Alice', active: true } ] ]
3. Sum with reduce
const nums = [1, 2, 3, 4, 5];
console.log(nums.reduce((a, b) => a + b, 0));
// [ 15 ]
4. Find user by id
const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
console.log(users.find(u => u.id === 2));
// [ { id: 2 } ]
5. Check if any match
console.log([1, 2, 3].some(n => n > 2));
// [ true ]
6. Check if all match
console.log([2, 4, 6].every(n => n % 2 === 0));
// [ true ]
7. Remove duplicates
const arr = [1, 2, 2, 3, 3, 3];
console.log([...new Set(arr)]);
// [ [ 1, 2, 3 ] ]
8. Sort objects by property
const users = [
{ name: 'Bob', age: 30 },
{ name: 'Alice', age: 25 }
];
const sorted = [...users].sort((a, b) => a.age - b.age);
console.log(sorted.map(u => u.name));
// [ [ 'Alice', 'Bob' ] ]
9. Group by property
const people = [
{ name: 'Alice', dept: 'Eng' },
{ name: 'Bob', dept: 'Sales' },
{ name: 'Charlie', dept: 'Eng' }
];
const byDept = people.reduce((acc, p) => {
(acc[p.dept] ||= []).push(p.name);
return acc;
}, {});
console.log(byDept);
// [ { Eng: [ 'Alice', 'Charlie' ], Sales: [ 'Bob' ] } ]
10. Word frequency
const text = 'the cat in the hat';
const counts = text.split(' ').reduce((acc, w) => {
acc[w] = (acc[w] || 0) + 1;
return acc;
}, {});
console.log(counts);
// [ { the: 2, cat: 1, in: 1, hat: 1 } ]
11. Flatten nested
console.log([1, [2, [3, [4]]]].flat(Infinity));
// [ [ 1, 2, 3, 4 ] ]
12. Chunk array
function chunk(arr, size) {
return Array.from(
{ length: Math.ceil(arr.length / size) },
(_, i) => arr.slice(i * size, i * size + size)
);
}
console.log(chunk([1, 2, 3, 4, 5], 2));
// [ [ [ 1, 2 ], [ 3, 4 ], [ 5 ] ] ]
13. Unique by property
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice2' }
];
const unique = [...new Map(users.map(u => [u.id, u])).values()];
console.log(unique);
// [ [ { id: 1, name: 'Alice2' }, { id: 2, name: 'Bob' } ] ]
14. Partition
function partition(arr, predicate) {
return arr.reduce(
([pass, fail], x) => predicate(x)
? [[...pass, x], fail]
: [pass, [...fail, x]],
[[], []]
);
}
console.log(partition([1, 2, 3, 4], n => n % 2 === 0));
// [ [ [ 2, 4 ], [ 1, 3 ] ] ]
15. Zip arrays
function zip(a, b) {
return a.map((x, i) => [x, b[i]]);
}
console.log(zip([1, 2, 3], ['a', 'b', 'c']));
// [ [ [ 1, 'a' ], [ 2, 'b' ], [ 3, 'c' ] ] ]
16. Compact (remove falsy)
console.log([0, 1, false, 2, '', 3].filter(Boolean));
// [ [ 1, 2, 3 ] ]
17. Range
function range(start, end) {
return Array.from({ length: end - start }, (_, i) => start + i);
}
console.log(range(1, 5));
// [ [ 1, 2, 3, 4 ] ]
18. Sum by property
const orders = [
{ total: 10 },
{ total: 20 },
{ total: 30 }
];
const sum = orders.reduce((acc, o) => acc + o.total, 0);
console.log(sum);
// [ 60 ]
19. Sort and dedupe
const arr = [3, 1, 2, 3, 1];
const result = [...new Set(arr)].sort((a, b) => a - b);
console.log(result);
// [ [ 1, 2, 3 ] ]
20. Full Script
const nums45 = [1, 2, 3, 4, 5];
nums45.map(n => n * 2);
nums45.filter(n => n > 2);
nums45.reduce((a, b) => a + b, 0);
nums45.find(n => n > 3);
nums45.findIndex(n => n > 3);
nums45.some(n => n > 4);
nums45.every(n => n > 0);
nums45.includes(3);
nums45.indexOf(4);
nums45.slice(1, 3);
nums45.concat([6, 7]);
nums45.flat();
nums45.flatMap(n => [n, n * 2]);
nums45.sort((a, b) => a - b);
nums45.reverse();
nums45.join('-');
nums45.forEach(n => console.log(n));
const arr45 = [3, 1, 2];
arr45.push(4);
arr45.pop();
arr45.unshift(0);
arr45.shift();
arr45.splice(1, 2, 'x');
arr45.fill(0);
arr45.copyWithin(0, 2);
Array.from('abc');
Array.of(1, 2, 3);
Array.isArray([]);
Visual: Mutating vs Non-Mutating
┌──────────────────────────────────────────────┐
│ MUTATING │
│ │
│ push, pop, shift, unshift │
│ splice, sort, reverse, fill, copyWithin │
│ │
│ arr = [1, 2, 3] │
│ arr.push(4) │
│ arr = [1, 2, 3, 4] ← SAME array │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ NON-MUTATING │
│ │
│ map, filter, slice, concat, flat, flatMap │
│ toSorted, toReversed, toSpliced, with │
│ │
│ arr = [1, 2, 3] │
│ const b = arr.map(x => x * 2) │
│ arr = [1, 2, 3] ← UNCHANGED │
│ b = [2, 4, 6] ← NEW array │
│ │
└──────────────────────────────────────────────┘
Visual: map vs forEach
┌──────────────────────────────────────────────┐
│ map │
│ │
│ [1, 2, 3].map(x => x * 2) │
│ │ │
│ ▼ │
│ [2, 4, 6] ← returns new array │
│ │
│ Use when you need a new array │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ forEach │
│ │
│ [1, 2, 3].forEach(x => console.log(x)) │
│ │ │
│ ▼ │
│ (prints 1, 2, 3) │
│ returns undefined │
│ │
│ Use for side effects only │
│ │
└──────────────────────────────────────────────┘
Visual: reduce
┌──────────────────────────────────────────────┐
│ [1, 2, 3, 4].reduce((a, b) => a + b, 0) │
│ │
│ acc=0, x=1 → 1 │
│ acc=1, x=2 → 3 │
│ acc=3, x=3 → 6 │
│ acc=6, x=4 → 10 │
│ │
│ returns 10 │
│ │
│ Fold the array into a single value │
│ │
└──────────────────────────────────────────────┘
Summary
| Method | Category | Returns |
|---|---|---|
map | Iterate | New array |
filter | Iterate | New array |
reduce | Iterate | Any |
reduceRight | Iterate | Any |
flatMap | Iterate | New array |
forEach | Iterate | undefined |
find | Search | Element |
findIndex | Search | Index |
findLast | Search | Element |
findLastIndex | Search | Index |
some | Search | Boolean |
every | Search | Boolean |
includes | Search | Boolean |
indexOf | Search | Index |
lastIndexOf | Search | Index |
push | Mutate | Length |
pop | Mutate | Element |
shift | Mutate | Element |
unshift | Mutate | Length |
splice | Mutate | Removed |
sort | Mutate | Array |
reverse | Mutate | Array |
fill | Mutate | Array |
copyWithin | Mutate | Array |
slice | Return | New array |
concat | Return | New array |
flat | Return | New array |
join | Return | String |
at | Return | Element |
toSorted | Return | New array |
toReversed | Return | New array |
toSpliced | Return | New array |
with | Return | New array |
Array.from | Static | New array |
Array.of | Static | New array |
Array.isArray | Static | Boolean |
Key takeaways:
maptransforms;filterselects;reduceaccumulatesfindis for objects;includesis for primitives andNaNsome= any match;every= all matchpush/pop/shift/unshift/splice/sort/reversemutate the arrayslice/concat/flat/flatMap/map/filterreturn new arrayssortis lexicographic by default — always pass a comparator for numbersindexOf(NaN)returns-1— useincludesinstead- Always provide an initial value to
reducefor empty arrays - Use
toSorted/toReversed/toSpliced/with(ES2023) for non-mutating operations - Chain methods for clean pipelines:
filter().map().reduce() Array.fromandArray.ofcreate arrays from iterables or argumentsArray.isArrayis the correct way to check for arrays
Remember: Arrays have dozens of methods, but they fall into four clear categories — iterating, searching, mutating, and returning. Know which is which and you’ll avoid the classic “why did my original array change?” bug. Reach for map/filter/reduce for transformations, find/some/every for checks, slice/concat/flat for new arrays, and only use push/splice/sort when you really mean to mutate. Master array methods, and your JavaScript becomes declarative, chainable, and readable.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!