Docs
6.2-Key-Array-Methods
12.2 Key Array Methods
Overview
Deep dive into the most important array methods that are essential for modern JavaScript development.
Method Categories
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ARRAY METHOD TYPES ā
āāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā MUTATING ā push, pop, shift, unshift, splice, ā
ā ā sort, reverse, fill, copyWithin ā
āāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā NON-MUTATING ā slice, concat, map, filter, reduce, ā
ā ā find, every, some, flat, flatMap ā
āāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā NEW COPIES ā toSorted, toReversed, toSpliced, ā
ā (ES2023) ā with ā
āāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Transformation Methods
map()
Creates a new array by transforming each element:
array.map(callback(element, index, array));
// Transform numbers
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((n) => n * 2);
// [2, 4, 6, 8, 10]
// Extract property
const users = [{ name: 'John' }, { name: 'Jane' }];
const names = users.map((u) => u.name);
// ['John', 'Jane']
// Transform objects
const formatted = users.map((u) => ({
...u,
displayName: u.name.toUpperCase(),
}));
filter()
Creates new array with elements that pass a test:
array.filter(callback(element, index, array));
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Basic filter
const evens = numbers.filter((n) => n % 2 === 0);
// [2, 4, 6, 8, 10]
// Filter objects
const products = [
{ name: 'Apple', price: 1.5, inStock: true },
{ name: 'Banana', price: 0.5, inStock: false },
{ name: 'Cherry', price: 2.0, inStock: true },
];
const available = products.filter((p) => p.inStock);
const affordable = products.filter((p) => p.price < 1);
reduce()
Reduces array to single value:
array.reduce(callback(accumulator, element, index, array), initialValue);
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā REDUCE FLOW ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā [1, 2, 3, 4, 5].reduce((acc, val) => acc + val, 0) ā
ā ā
ā Step 1: acc=0, val=1 ā 0 + 1 = 1 ā
ā Step 2: acc=1, val=2 ā 1 + 2 = 3 ā
ā Step 3: acc=3, val=3 ā 3 + 3 = 6 ā
ā Step 4: acc=6, val=4 ā 6 + 4 = 10 ā
ā Step 5: acc=10, val=5 ā 10 + 5 = 15 ā
ā ā
ā Result: 15 ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Common reduce patterns:
// Sum
const sum = nums.reduce((a, b) => a + b, 0);
// Count occurrences
const counts = items.reduce((acc, item) => {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});
// Group by property
const grouped = people.reduce((acc, person) => {
const key = person.department;
(acc[key] = acc[key] || []).push(person);
return acc;
}, {});
// Flatten one level
const flat = nested.reduce((acc, arr) => [...acc, ...arr], []);
// Build object from entries
const obj = entries.reduce((acc, [key, value]) => {
acc[key] = value;
return acc;
}, {});
reduceRight()
Same as reduce but processes right to left:
const arr = [
[1, 2],
[3, 4],
[5, 6],
];
// Left to right
arr.reduce((a, b) => a.concat(b)); // [1, 2, 3, 4, 5, 6]
// Right to left
arr.reduceRight((a, b) => a.concat(b)); // [5, 6, 3, 4, 1, 2]
Search Methods
| Method | Returns | When to Use |
|---|---|---|
find() | First matching element or undefined | Need the actual element |
findIndex() | Index of first match or -1 | Need the position |
findLast() | Last matching element | Search from end |
findLastIndex() | Index of last match | Position from end |
indexOf() | Index of value or -1 | Simple value lookup |
lastIndexOf() | Last index of value | Find last occurrence |
includes() | Boolean | Just check existence |
const users = [
{ id: 1, name: 'John', active: true },
{ id: 2, name: 'Jane', active: false },
{ id: 3, name: 'Bob', active: true },
];
// find - get element
const john = users.find((u) => u.name === 'John');
// { id: 1, name: 'John', active: true }
// findIndex - get position
const janeIndex = users.findIndex((u) => u.name === 'Jane');
// 1
// findLast - from end (ES2023)
const lastActive = users.findLast((u) => u.active);
// { id: 3, name: 'Bob', active: true }
// includes - check existence
const numbers = [1, 2, 3, 4, 5];
numbers.includes(3); // true
numbers.includes(10); // false
numbers.includes(3, 3); // false (start from index 3)
Testing Methods
every() and some()
array.every(callback); // All must pass
array.some(callback); // At least one must pass
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā every() - Returns true if ALL elements pass ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā [2, 4, 6].every(n => n % 2 === 0) ā true ā
ā [2, 3, 6].every(n => n % 2 === 0) ā false ā
ā ā
ā Short-circuits on first failure ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā some() - Returns true if ANY element passes ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā [1, 2, 3].some(n => n > 2) ā true ā
ā [1, 2, 3].some(n => n > 5) ā false ā
ā ā
ā Short-circuits on first success ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
const orders = [
{ id: 1, total: 100, paid: true },
{ id: 2, total: 50, paid: true },
{ id: 3, total: 75, paid: false },
];
// Check all paid
const allPaid = orders.every((o) => o.paid); // false
// Check if any unpaid
const hasUnpaid = orders.some((o) => !o.paid); // true
// Validate data
const isValid = data.every((item) => item.name && item.email && item.age > 0);
Flattening Methods
flat()
array.flat((depth = 1));
const nested = [1, [2, 3], [4, [5, 6]]];
nested.flat(); // [1, 2, 3, 4, [5, 6]]
nested.flat(2); // [1, 2, 3, 4, 5, 6]
nested.flat(Infinity); // [1, 2, 3, 4, 5, 6]
// Remove empty slots
const sparse = [1, , 3, , 5];
sparse.flat(); // [1, 3, 5]
flatMap()
Combines map and flat(1):
const sentences = ['Hello World', 'How are you'];
// Using map + flat
sentences.map((s) => s.split(' ')).flat();
// ['Hello', 'World', 'How', 'are', 'you']
// Using flatMap (more efficient)
sentences.flatMap((s) => s.split(' '));
// ['Hello', 'World', 'How', 'are', 'you']
// Conditional expansion
const nums = [1, 2, 3];
nums.flatMap((n) => (n > 1 ? [n, n * 2] : []));
// [2, 4, 3, 6]
ES2023 Non-Mutating Alternatives
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ES2023 COPYING METHODS ā
āāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā MUTATING ā NON-MUTATING (ES2023) ā
āāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā array.sort() ā array.toSorted() ā
ā array.reverse() ā array.toReversed() ā
ā array.splice() ā array.toSpliced() ā
ā array[i] = val ā array.with(i, val) ā
āāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
const arr = [3, 1, 4, 1, 5];
// toSorted - non-mutating sort
const sorted = arr.toSorted((a, b) => a - b);
console.log(sorted); // [1, 1, 3, 4, 5]
console.log(arr); // [3, 1, 4, 1, 5] - unchanged
// toReversed - non-mutating reverse
const reversed = arr.toReversed();
console.log(reversed); // [5, 1, 4, 1, 3]
console.log(arr); // [3, 1, 4, 1, 5] - unchanged
// toSpliced - non-mutating splice
const spliced = arr.toSpliced(1, 2, 'a', 'b');
console.log(spliced); // [3, 'a', 'b', 1, 5]
console.log(arr); // [3, 1, 4, 1, 5] - unchanged
// with - non-mutating index assignment
const updated = arr.with(2, 99);
console.log(updated); // [3, 1, 99, 1, 5]
console.log(arr); // [3, 1, 4, 1, 5] - unchanged
Sorting
Default Sort (Alphabetical)
// ā ļø Default sort converts to strings
[10, 2, 30, 1].sort(); // [1, 10, 2, 30] - Wrong!
// ā
Numeric sort
[10, 2, 30, 1].sort((a, b) => a - b); // [1, 2, 10, 30]
Compare Function
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā SORT COMPARE FUNCTION ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā compare(a, b) returns: ā
ā ā
ā ⢠Negative: a comes before b ā
ā ⢠Zero: keep original order ā
ā ⢠Positive: a comes after b ā
ā ā
ā Ascending: (a, b) => a - b ā
ā Descending: (a, b) => b - a ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Sort Patterns
// Numbers ascending
numbers.sort((a, b) => a - b);
// Numbers descending
numbers.sort((a, b) => b - a);
// Strings (case-insensitive)
strings.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
// Objects by property
users.sort((a, b) => a.age - b.age);
users.sort((a, b) => a.name.localeCompare(b.name));
// Multiple criteria
users.sort((a, b) => {
if (a.department !== b.department) {
return a.department.localeCompare(b.department);
}
return a.name.localeCompare(b.name);
});
// Random shuffle
array.sort(() => Math.random() - 0.5); // Not perfectly uniform!
Iteration Methods
forEach()
array.forEach(callback(element, index, array));
const items = ['a', 'b', 'c'];
items.forEach((item, index) => {
console.log(`${index}: ${item}`);
});
// ā ļø Cannot break or return early
// ā ļø Returns undefined
entries(), keys(), values()
const arr = ['a', 'b', 'c'];
// Iterate with index
for (const [index, value] of arr.entries()) {
console.log(index, value);
}
// Just keys (indices)
for (const key of arr.keys()) {
console.log(key); // 0, 1, 2
}
// Just values
for (const value of arr.values()) {
console.log(value); // 'a', 'b', 'c'
}
Concatenation and Joining
// concat - combine arrays
const a = [1, 2];
const b = [3, 4];
const combined = a.concat(b); // [1, 2, 3, 4]
const withMore = a.concat(b, 5, [6, 7]); // [1, 2, 3, 4, 5, 6, 7]
// join - array to string
const words = ['Hello', 'World'];
words.join(' '); // 'Hello World'
words.join('-'); // 'Hello-World'
words.join(''); // 'HelloWorld'
words.join(); // 'Hello,World' (default comma)
Method Chaining
Combine methods for powerful data transformations:
const transactions = [
{ type: 'sale', amount: 100, date: '2024-01-15' },
{ type: 'refund', amount: 50, date: '2024-01-16' },
{ type: 'sale', amount: 200, date: '2024-01-17' },
{ type: 'sale', amount: 75, date: '2024-01-18' },
];
// Calculate total sales for January
const januarySalesTotal = transactions
.filter((t) => t.type === 'sale') // Only sales
.filter((t) => t.date.startsWith('2024-01')) // Only January
.map((t) => t.amount) // Extract amounts
.reduce((sum, amount) => sum + amount, 0); // Sum up
console.log(januarySalesTotal); // 375
Performance Considerations
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā PERFORMANCE TIPS ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā 1. Avoid multiple passes when possible ā
ā ā arr.filter(...).map(...).filter(...) ā
ā ā
arr.reduce(...) - single pass ā
ā ā
ā 2. Use early termination methods ā
ā find(), some(), every() stop when answer is known ā
ā ā
ā 3. Consider array size ā
ā - Small arrays: readability > performance ā
ā - Large arrays: optimize hot paths ā
ā ā
ā 4. Mutation can be faster ā
ā - Creating copies has overhead ā
ā - Mutate when safe (local scope, no shared refs) ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Quick Reference
| Method | Mutates | Returns | Purpose |
|---|---|---|---|
map() | No | New array | Transform elements |
filter() | No | New array | Select elements |
reduce() | No | Single value | Aggregate |
find() | No | Element | First match |
findIndex() | No | Number | Index of first match |
every() | No | Boolean | All pass test |
some() | No | Boolean | Any pass test |
flat() | No | New array | Flatten nesting |
flatMap() | No | New array | Map + flatten |
sort() | Yes | Same array | Sort in place |
toSorted() | No | New array | Sort copy |
reverse() | Yes | Same array | Reverse in place |
toReversed() | No | New array | Reverse copy |
Key Takeaways
- ā¢map, filter, reduce - The "big three" for data transformation
- ā¢find vs filter - find returns one, filter returns array
- ā¢every vs some - all vs any, both short-circuit
- ā¢ES2023 methods - toSorted, toReversed, toSpliced, with for immutability
- ā¢Chain methods - Combine for readable data pipelines
- ā¢Know mutation - Check if method modifies original