Skip to content

Array Methods and Utilities

Arrays are one of the most fundamental and versatile data structures in JavaScript. This comprehensive guide covers all array methods, advanced manipulation techniques, and practical patterns for working with arrays effectively.

// Array.of() - Create array from arguments
const numbers = Array.of(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
const singleItem = Array.of(7); // [7] (not array with 7 empty slots)
const mixed = Array.of('a', 1, true, null); // ['a', 1, true, null]
// Array.from() - Create array from iterable or array-like
const fromString = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
const fromSet = Array.from(new Set([1, 2, 3])); // [1, 2, 3]
const range = Array.from({ length: 5 }, (_, i) => i + 1); // [1, 2, 3, 4, 5]
// Array.from() with mapping function
const doubled = Array.from([1, 2, 3], x => x * 2); // [2, 4, 6]
const squares = Array.from({ length: 5 }, (_, i) => i ** 2); // [0, 1, 4, 9, 16]
// Convert NodeList to Array
const elements = Array.from(document.querySelectorAll('div'));
// Convert arguments object to Array
function toArray() {
return Array.from(arguments);
}
// Array.fromAsync() - ES2023 proposal for async iterables
async function* asyncGenerator() {
for (let i = 0; i < 3; i++) {
yield Promise.resolve(i);
}
}
// const asyncArray = await Array.fromAsync(asyncGenerator()); // [0, 1, 2]
// Array literals (preferred)
const fruits = ['apple', 'banana', 'cherry'];
const numbers = [1, 2, 3, 4, 5];
const mixed = [1, 'hello', true, null, { id: 1 }];
// Array constructor patterns
const empty = new Array(); // []
const withLength = new Array(5); // [undefined × 5]
const withElements = new Array(1, 2, 3); // [1, 2, 3]
// Sparse arrays
const sparse = [1, , , 4]; // [1, undefined × 2, 4]
console.log(sparse.length); // 4
console.log(sparse[1]); // undefined
console.log(1 in sparse); // false
// Multi-dimensional arrays
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// Create 2D array dynamically
function create2DArray(rows, cols, defaultValue = null) {
return Array.from({ length: rows }, () =>
Array.from({ length: cols }, () => defaultValue)
);
}
const grid = create2DArray(3, 3, 0);
// [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
const arr = [1, 2, 3];
// push() - Add to end (returns new length)
const newLength = arr.push(4, 5); // arr: [1, 2, 3, 4, 5], returns: 5
// pop() - Remove from end (returns removed element)
const removed = arr.pop(); // arr: [1, 2, 3, 4], returns: 5
// unshift() - Add to beginning (returns new length)
arr.unshift(0); // arr: [0, 1, 2, 3, 4], returns: 5
// shift() - Remove from beginning (returns removed element)
const first = arr.shift(); // arr: [1, 2, 3, 4], returns: 0
// Performance comparison: push/pop vs unshift/shift
console.time('push/pop');
const arr1 = [];
for (let i = 0; i < 100000; i++) {
arr1.push(i);
}
for (let i = 0; i < 100000; i++) {
arr1.pop();
}
console.timeEnd('push/pop'); // Usually faster
console.time('unshift/shift');
const arr2 = [];
for (let i = 0; i < 100000; i++) {
arr2.unshift(i);
}
for (let i = 0; i < 100000; i++) {
arr2.shift();
}
console.timeEnd('unshift/shift'); // Usually slower
const arr = ['a', 'b', 'c', 'd', 'e'];
// Remove elements
const removed1 = arr.splice(1, 2); // arr: ['a', 'd', 'e'], removed: ['b', 'c']
// Insert elements
arr.splice(1, 0, 'x', 'y'); // arr: ['a', 'x', 'y', 'd', 'e']
// Replace elements
arr.splice(1, 2, 'z'); // arr: ['a', 'z', 'd', 'e']
// Insert at specific position
function insertAt(array, index, ...elements) {
array.splice(index, 0, ...elements);
return array;
}
// Remove all occurrences of a value
function removeAll(array, value) {
for (let i = array.length - 1; i >= 0; i--) {
if (array[i] === value) {
array.splice(i, 1);
}
}
return array;
}
// Move element from one position to another
function moveElement(array, fromIndex, toIndex) {
const element = array.splice(fromIndex, 1)[0];
array.splice(toIndex, 0, element);
return array;
}
const letters = ['a', 'b', 'c', 'd', 'e'];
moveElement(letters, 1, 3); // ['a', 'c', 'd', 'b', 'e']
const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
const strings = ['banana', 'apple', 'cherry', 'date'];
// Basic sorting
numbers.sort(); // [1, 1, 2, 3, 4, 5, 6, 9]
strings.sort(); // ['apple', 'banana', 'cherry', 'date']
// Numeric sorting (important!)
const nums = [10, 2, 1, 20];
nums.sort(); // ['1', '10', '2', '20'] - WRONG!
nums.sort((a, b) => a - b); // [1, 2, 10, 20] - Correct
// Custom sorting functions
const people = [
{ name: 'Alice', age: 30, salary: 50000 },
{ name: 'Bob', age: 25, salary: 60000 },
{ name: 'Charlie', age: 35, salary: 45000 }
];
// Sort by age (ascending)
people.sort((a, b) => a.age - b.age);
// Sort by name (alphabetical)
people.sort((a, b) => a.name.localeCompare(b.name));
// Sort by multiple criteria
people.sort((a, b) => {
// First by age, then by salary
if (a.age !== b.age) {
return a.age - b.age;
}
return b.salary - a.salary; // Descending salary
});
// Stable sort function
function stableSort(array, compareFn) {
const indexed = array.map((item, index) => ({ item, index }));
indexed.sort((a, b) => {
const result = compareFn(a.item, b.item);
return result !== 0 ? result : a.index - b.index;
});
return indexed.map(({ item }) => item);
}
// Reverse array
const original = [1, 2, 3, 4, 5];
const reversed = original.reverse(); // [5, 4, 3, 2, 1] - mutates original!
// Non-mutating reverse
const reversedCopy = [...original].reverse();
const reversedSlice = original.slice().reverse();
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// slice() - Extract portion (doesn't mutate)
const subset = arr.slice(2, 6); // [3, 4, 5, 6]
const fromIndex = arr.slice(3); // [4, 5, 6, 7, 8, 9, 10]
const lastThree = arr.slice(-3); // [8, 9, 10]
const copy = arr.slice(); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// Negative indices
const negativeSlice = arr.slice(-5, -2); // [6, 7, 8]
// concat() - Combine arrays (doesn't mutate)
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = arr1.concat(arr2); // [1, 2, 3, 4, 5, 6]
const multiConcat = arr1.concat(arr2, [7, 8], 9); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// Spread operator alternative
const spreadCombined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// join() - Convert to string
const numbers = [1, 2, 3, 4, 5];
const joined = numbers.join(', '); // '1, 2, 3, 4, 5'
const path = ['home', 'user', 'documents'].join('/'); // 'home/user/documents'
const noSeparator = numbers.join(''); // '12345'
// toString() vs join()
console.log(numbers.toString()); // '1,2,3,4,5'
console.log(numbers.join()); // '1,2,3,4,5' (same as toString)
const arr = [1, 2, 3, 4, 3, 5, 6];
const people = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 35 }
];
// indexOf() and lastIndexOf()
const index = arr.indexOf(3); // 2 (first occurrence)
const lastIndex = arr.lastIndexOf(3); // 4 (last occurrence)
const notFound = arr.indexOf(10); // -1
// includes() - Check if element exists
const hasThree = arr.includes(3); // true
const hasFromIndex = arr.includes(3, 3); // true (search from index 3)
// find() - Find first matching element
const person = people.find(p => p.age > 30); // { name: 'Charlie', age: 35 }
const notFoundPerson = people.find(p => p.age > 40); // undefined
// findIndex() - Find index of first matching element
const personIndex = people.findIndex(p => p.name === 'Bob'); // 1
const notFoundIndex = people.findIndex(p => p.age > 40); // -1
// findLast() and findLastIndex() - ES2023
const lastMatch = arr.findLast(x => x > 3); // 6 (if available)
const lastMatchIndex = arr.findLastIndex(x => x > 3); // 6 (if available)
// some() - Test if at least one element passes
const hasAdult = people.some(p => p.age >= 18); // true
const hasMinor = people.some(p => p.age < 18); // false
// every() - Test if all elements pass
const allAdults = people.every(p => p.age >= 18); // true
const allSeniors = people.every(p => p.age >= 65); // false
// Advanced search with custom predicates
function findByProperty(array, property, value) {
return array.find(item => item[property] === value);
}
function findAllByProperty(array, property, value) {
return array.filter(item => item[property] === value);
}
function findWithMultipleCriteria(array, criteria) {
return array.find(item =>
Object.keys(criteria).every(key => item[key] === criteria[key])
);
}
const employee = findWithMultipleCriteria(people, { name: 'Alice', age: 30 });
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// map() - Transform each element
const doubled = numbers.map(x => x * 2); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
const squared = numbers.map(x => x ** 2); // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
const strings = numbers.map(x => `Number: ${x}`); // ['Number: 1', 'Number: 2', ...]
// Map with index and array parameters
const withIndex = numbers.map((value, index, array) => ({
value,
index,
isLast: index === array.length - 1
}));
// filter() - Select elements based on condition
const evens = numbers.filter(x => x % 2 === 0); // [2, 4, 6, 8, 10]
const greaterThanFive = numbers.filter(x => x > 5); // [6, 7, 8, 9, 10]
// Complex filtering
const users = [
{ name: 'Alice', age: 25, active: true, role: 'admin' },
{ name: 'Bob', age: 30, active: false, role: 'user' },
{ name: 'Charlie', age: 35, active: true, role: 'user' },
{ name: 'Diana', age: 28, active: true, role: 'admin' }
];
const activeAdmins = users.filter(user => user.active && user.role === 'admin');
const youngUsers = users.filter(user => user.age < 30);
// reduce() - Accumulate values
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 55
const product = numbers.reduce((acc, curr) => acc * curr, 1); // 3628800
const max = numbers.reduce((acc, curr) => Math.max(acc, curr)); // 10
// Advanced reduce examples
const groupedUsers = users.reduce((groups, user) => {
const key = user.role;
if (!groups[key]) {
groups[key] = [];
}
groups[key].push(user);
return groups;
}, {});
const userStats = users.reduce((stats, user) => {
stats.total++;
if (user.active) stats.active++;
if (user.role === 'admin') stats.admins++;
stats.averageAge = (stats.averageAge * (stats.total - 1) + user.age) / stats.total;
return stats;
}, { total: 0, active: 0, admins: 0, averageAge: 0 });
// reduceRight() - Process from right to left
const rightToLeft = [1, 2, 3, 4].reduceRight((acc, curr) => acc - curr); // -2
// Implementing map and filter with reduce
function mapWithReduce(array, mapper) {
return array.reduce((acc, curr, index, arr) => {
acc.push(mapper(curr, index, arr));
return acc;
}, []);
}
function filterWithReduce(array, predicate) {
return array.reduce((acc, curr, index, arr) => {
if (predicate(curr, index, arr)) {
acc.push(curr);
}
return acc;
}, []);
}
// flat() - Flatten nested arrays
const nested = [[1, 2], [3, 4], [5, 6]];
const flattened = nested.flat(); // [1, 2, 3, 4, 5, 6]
const deepNested = [1, [2, [3, [4, 5]]]];
const flatLevel1 = deepNested.flat(); // [1, 2, [3, [4, 5]]]
const flatLevel2 = deepNested.flat(2); // [1, 2, 3, [4, 5]]
const completelyFlat = deepNested.flat(Infinity); // [1, 2, 3, 4, 5]
// flatMap() - Map then flatten (only one level)
const words = ['hello', 'world'];
const letters = words.flatMap(word => word.split('')); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
const sentences = ['Hello world', 'How are you'];
const allWords = sentences.flatMap(sentence => sentence.split(' ')); // ['Hello', 'world', 'How', 'are', 'you']
// Complex flatMap example
const users = [
{ name: 'Alice', hobbies: ['reading', 'swimming'] },
{ name: 'Bob', hobbies: ['gaming', 'cooking', 'reading'] },
{ name: 'Charlie', hobbies: ['swimming', 'hiking'] }
];
const allHobbies = users.flatMap(user => user.hobbies);
const uniqueHobbies = [...new Set(allHobbies)];
// Custom flatten function for deeper control
function flattenDeep(arr) {
return Array.isArray(arr)
? arr.reduce((acc, val) => acc.concat(flattenDeep(val)), [])
: [arr];
}
function flattenToDepth(arr, depth = 1) {
if (depth <= 0) return arr;
return arr.reduce((acc, val) =>
Array.isArray(val)
? acc.concat(flattenToDepth(val, depth - 1))
: acc.concat(val),
[]
);
}
// Method chaining for complex operations
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const result = numbers
.filter(x => x % 2 === 0) // [2, 4, 6, 8, 10]
.map(x => x ** 2) // [4, 16, 36, 64, 100]
.filter(x => x > 20) // [36, 64, 100]
.reduce((sum, x) => sum + x, 0); // 200
// Complex data transformation pipeline
const salesData = [
{ region: 'North', sales: [100, 200, 150], quarter: 'Q1' },
{ region: 'South', sales: [80, 120, 90], quarter: 'Q1' },
{ region: 'North', sales: [180, 220, 200], quarter: 'Q2' },
{ region: 'South', sales: [95, 110, 85], quarter: 'Q2' }
];
const analysis = salesData
.map(item => ({
...item,
total: item.sales.reduce((sum, sale) => sum + sale, 0),
average: item.sales.reduce((sum, sale) => sum + sale, 0) / item.sales.length
}))
.filter(item => item.total > 250)
.sort((a, b) => b.total - a.total)
.map(item => ({
region: item.region,
quarter: item.quarter,
performance: item.total > 400 ? 'Excellent' : 'Good'
}));
// Functional composition helpers
const pipe = (...functions) => (value) =>
functions.reduce((acc, fn) => fn(acc), value);
const compose = (...functions) => (value) =>
functions.reduceRight((acc, fn) => fn(acc), value);
// Usage
const transformNumbers = pipe(
arr => arr.filter(x => x > 0),
arr => arr.map(x => x * 2),
arr => arr.sort((a, b) => a - b)
);
const transformed = transformNumbers([-1, 3, -2, 5, 1]);
// Array equality comparison
function arrayEquals(a, b) {
if (a.length !== b.length) return false;
return a.every((val, index) => val === b[index]);
}
function deepArrayEquals(a, b) {
if (a.length !== b.length) return false;
return a.every((val, index) => {
if (Array.isArray(val) && Array.isArray(b[index])) {
return deepArrayEquals(val, b[index]);
}
return val === b[index];
});
}
// Array intersection, union, difference
function intersection(arr1, arr2) {
return arr1.filter(x => arr2.includes(x));
}
function union(arr1, arr2) {
return [...new Set([...arr1, ...arr2])];
}
function difference(arr1, arr2) {
return arr1.filter(x => !arr2.includes(x));
}
function symmetricDifference(arr1, arr2) {
return [
...arr1.filter(x => !arr2.includes(x)),
...arr2.filter(x => !arr1.includes(x))
];
}
// Chunk array into smaller arrays
function chunk(array, size) {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
// Shuffle array (Fisher-Yates algorithm)
function shuffle(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
// Sample random elements
function sample(array, n = 1) {
const shuffled = shuffle(array);
return n === 1 ? shuffled[0] : shuffled.slice(0, n);
}
// Partition array based on predicate
function partition(array, predicate) {
const passed = [];
const failed = [];
array.forEach(item => {
if (predicate(item)) {
passed.push(item);
} else {
failed.push(item);
}
});
return [passed, failed];
}
// Group consecutive elements
function groupConsecutive(array, keyFn = x => x) {
const groups = [];
let currentGroup = [];
let lastKey = Symbol('initial');
for (const item of array) {
const key = keyFn(item);
if (key !== lastKey) {
if (currentGroup.length > 0) {
groups.push(currentGroup);
}
currentGroup = [item];
lastKey = key;
} else {
currentGroup.push(item);
}
}
if (currentGroup.length > 0) {
groups.push(currentGroup);
}
return groups;
}
// Usage examples
console.log(intersection([1, 2, 3], [2, 3, 4])); // [2, 3]
console.log(union([1, 2, 3], [2, 3, 4])); // [1, 2, 3, 4]
console.log(difference([1, 2, 3], [2, 3, 4])); // [1]
console.log(symmetricDifference([1, 2, 3], [2, 3, 4])); // [1, 4]
console.log(chunk([1, 2, 3, 4, 5, 6, 7], 3)); // [[1, 2, 3], [4, 5, 6], [7]]
console.log(sample([1, 2, 3, 4, 5], 3)); // Random 3 elements
console.log(partition([1, 2, 3, 4, 5], x => x % 2 === 0)); // [[2, 4], [1, 3, 5]]

This comprehensive guide covers the vast majority of array operations and techniques in JavaScript. Arrays are incredibly powerful and versatile, and mastering these methods will significantly improve your JavaScript programming skills.


Practice these array methods and patterns to become proficient in JavaScript data manipulation.