JavaScript BasicsFeatured

JavaScript Array Methods: The Ultimate Guide

Complete guide to JavaScript array methods with examples. Master array manipulation, transformation, iteration, and modern array handling techniques.

By JavaScript Document Team
arraysmethodsbasicsreferencemanipulation

Arrays are fundamental data structures in JavaScript, providing powerful methods for data manipulation and transformation. This comprehensive guide covers all JavaScript array methods with practical examples to help you master array operations.

Array Creation

Array Literals and Constructor

// Array literal (preferred)
const arr1 = [1, 2, 3, 4, 5];
const arr2 = ['apple', 'banana', 'orange'];
const arr3 = [1, 'two', true, null, undefined];

// Array constructor
const arr4 = new Array(5); // Creates array with 5 empty slots
const arr5 = new Array(1, 2, 3); // Creates [1, 2, 3]

// Array.of() - creates array from arguments
const arr6 = Array.of(5); // [5] (not empty array)
const arr7 = Array.of(1, 2, 3); // [1, 2, 3]

// Array.from() - creates array from iterable
const arr8 = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
const arr9 = Array.from([1, 2, 3], (x) => x * 2); // [2, 4, 6]

// Creating array with specific length and values
const zeros = Array(5).fill(0); // [0, 0, 0, 0, 0]
const sequence = Array.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4]

Array Properties

length

const fruits = ['apple', 'banana', 'orange'];

console.log(fruits.length); // 3

// Modifying length
fruits.length = 2;
console.log(fruits); // ['apple', 'banana']

fruits.length = 5;
console.log(fruits); // ['apple', 'banana', empty × 3]

// Truncating array
const numbers = [1, 2, 3, 4, 5];
numbers.length = 0; // Empties the array
console.log(numbers); // []

Adding and Removing Elements

push() and pop()

const stack = [];

// push() - adds elements to end, returns new length
console.log(stack.push(1)); // 1
console.log(stack.push(2, 3)); // 3
console.log(stack); // [1, 2, 3]

// pop() - removes and returns last element
console.log(stack.pop()); // 3
console.log(stack); // [1, 2]
console.log(stack.pop()); // 2
console.log(stack.pop()); // 1
console.log(stack.pop()); // undefined (empty array)

unshift() and shift()

const queue = [];

// unshift() - adds elements to beginning, returns new length
console.log(queue.unshift(1)); // 1
console.log(queue.unshift(2, 3)); // 3
console.log(queue); // [2, 3, 1]

// shift() - removes and returns first element
console.log(queue.shift()); // 2
console.log(queue); // [3, 1]
console.log(queue.shift()); // 3
console.log(queue.shift()); // 1
console.log(queue.shift()); // undefined

splice()

const arr = ['a', 'b', 'c', 'd', 'e'];

// Remove elements: splice(start, deleteCount)
const removed = arr.splice(2, 2);
console.log(arr); // ['a', 'b', 'e']
console.log(removed); // ['c', 'd']

// Insert elements: splice(start, 0, ...items)
arr.splice(1, 0, 'x', 'y');
console.log(arr); // ['a', 'x', 'y', 'b', 'e']

// Replace elements: splice(start, deleteCount, ...items)
arr.splice(2, 2, 'z');
console.log(arr); // ['a', 'x', 'z', 'e']

// Negative index
arr.splice(-1, 1, 'END');
console.log(arr); // ['a', 'x', 'z', 'END']

Array Transformation Methods

map()

const numbers = [1, 2, 3, 4, 5];

// Basic transformation
const doubled = numbers.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// With index and array parameters
const indexed = numbers.map((value, index, array) => {
  return `${index}: ${value} of ${array.length}`;
});
console.log(indexed);
// ['0: 1 of 5', '1: 2 of 5', '2: 3 of 5', '3: 4 of 5', '4: 5 of 5']

// Object transformation
const users = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 35 },
];

const names = users.map((user) => user.name);
console.log(names); // ['Alice', 'Bob', 'Charlie']

const enhanced = users.map((user) => ({
  ...user,
  isAdult: user.age >= 18,
  category: user.age < 30 ? 'young' : 'adult',
}));

filter()

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Basic filtering
const evens = numbers.filter((n) => n % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]

// Complex filtering
const products = [
  { name: 'Laptop', price: 999, inStock: true },
  { name: 'Mouse', price: 29, inStock: false },
  { name: 'Keyboard', price: 79, inStock: true },
  { name: 'Monitor', price: 299, inStock: true },
];

const availableUnder100 = products.filter(
  (product) => product.inStock && product.price < 100
);
console.log(availableUnder100);
// [{ name: 'Keyboard', price: 79, inStock: true }]

// Chaining with map
const affordableNames = products
  .filter((p) => p.price < 300)
  .map((p) => p.name);
console.log(affordableNames); // ['Mouse', 'Keyboard', 'Monitor']

reduce()

const numbers = [1, 2, 3, 4, 5];

// Sum
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15

// Product
const product = numbers.reduce((acc, num) => acc * num, 1);
console.log(product); // 120

// Find max
const max = numbers.reduce((max, num) => (num > max ? num : max));
console.log(max); // 5

// Group by property
const people = [
  { name: 'Alice', age: 25, city: 'NYC' },
  { name: 'Bob', age: 30, city: 'LA' },
  { name: 'Charlie', age: 35, city: 'NYC' },
  { name: 'David', age: 40, city: 'LA' },
];

const byCity = people.reduce((groups, person) => {
  const city = person.city;
  if (!groups[city]) groups[city] = [];
  groups[city].push(person);
  return groups;
}, {});

console.log(byCity);
// { NYC: [{Alice}, {Charlie}], LA: [{Bob}, {David}] }

// Flatten array
const nested = [
  [1, 2],
  [3, 4],
  [5, 6],
];
const flat = nested.reduce((acc, arr) => acc.concat(arr), []);
console.log(flat); // [1, 2, 3, 4, 5, 6]

reduceRight()

const numbers = [1, 2, 3, 4, 5];

// Right-to-left reduction
const result = numbers.reduceRight((acc, num) => {
  console.log(`${acc} - ${num}`);
  return acc - num;
});
// 5 - 4
// 1 - 3
// -2 - 2
// -4 - 1
console.log(result); // -5

// Building string from right to left
const words = ['World', 'Hello'];
const sentence = words.reduceRight((acc, word) => acc + ' ' + word);
console.log(sentence); // 'Hello World'

Searching and Finding

find() and findIndex()

const users = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 },
  { id: 3, name: 'Charlie', age: 35 },
];

// find() - returns first matching element
const user = users.find((u) => u.age > 28);
console.log(user); // { id: 2, name: 'Bob', age: 30 }

const noUser = users.find((u) => u.age > 40);
console.log(noUser); // undefined

// findIndex() - returns index of first match
const index = users.findIndex((u) => u.name === 'Charlie');
console.log(index); // 2

const noIndex = users.findIndex((u) => u.name === 'David');
console.log(noIndex); // -1

findLast() and findLastIndex()

const numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];

// findLast() - returns last matching element (ES2023)
const lastEven = numbers.findLast((n) => n % 2 === 0);
console.log(lastEven); // 2

// findLastIndex() - returns index of last match (ES2023)
const lastIndexOf4 = numbers.findLastIndex((n) => n === 4);
console.log(lastIndexOf4); // 5

indexOf() and lastIndexOf()

const arr = ['a', 'b', 'c', 'b', 'a'];

// indexOf() - first occurrence
console.log(arr.indexOf('b')); // 1
console.log(arr.indexOf('d')); // -1
console.log(arr.indexOf('b', 2)); // 3 (search from index 2)

// lastIndexOf() - last occurrence
console.log(arr.lastIndexOf('b')); // 3
console.log(arr.lastIndexOf('b', 2)); // 1 (search backwards from index 2)

// Checking existence
const hasB = arr.indexOf('b') !== -1;
console.log(hasB); // true

includes()

const arr = [1, 2, 3, NaN];

console.log(arr.includes(2)); // true
console.log(arr.includes(4)); // false
console.log(arr.includes(NaN)); // true (works with NaN!)

// With fromIndex
console.log(arr.includes(1, 1)); // false (search from index 1)
console.log(arr.includes(3, -2)); // true (search from index 2)

// vs indexOf
console.log(arr.indexOf(NaN)); // -1 (doesn't work with NaN)
console.log(arr.includes(NaN)); // true

Testing Methods

every() and some()

const numbers = [2, 4, 6, 8, 10];

// every() - tests if all elements pass
const allEven = numbers.every((n) => n % 2 === 0);
console.log(allEven); // true

const allGreaterThan5 = numbers.every((n) => n > 5);
console.log(allGreaterThan5); // false

// some() - tests if at least one element passes
const someGreaterThan5 = numbers.some((n) => n > 5);
console.log(someGreaterThan5); // true

const someOdd = numbers.some((n) => n % 2 !== 0);
console.log(someOdd); // false

// Empty array behavior
console.log([].every((x) => false)); // true (vacuous truth)
console.log([].some((x) => true)); // false

Iteration Methods

forEach()

const fruits = ['apple', 'banana', 'orange'];

// Basic iteration
fruits.forEach((fruit) => console.log(fruit));

// With index and array
fruits.forEach((fruit, index, array) => {
  console.log(`${index}: ${fruit} (${array.length} total)`);
});

// Cannot break out of forEach
let count = 0;
fruits.forEach((fruit) => {
  if (count >= 2) return; // This doesn't break the loop
  console.log(fruit);
  count++;
});
// Still logs all fruits

// Side effects
const numbers = [1, 2, 3];
const doubled = [];
numbers.forEach((n) => doubled.push(n * 2));
console.log(doubled); // [2, 4, 6]

for...of

const arr = ['a', 'b', 'c'];

// Basic iteration
for (const value of arr) {
  console.log(value); // a, b, c
}

// With index using entries()
for (const [index, value] of arr.entries()) {
  console.log(`${index}: ${value}`);
}

// Can break/continue
for (const value of arr) {
  if (value === 'b') break;
  console.log(value); // Only logs 'a'
}

Array Flattening

flat() and flatMap()

// flat() - flattens 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]

// Removing empty slots
const sparse = [1, , 3, , 5];
console.log(sparse.flat()); // [1, 3, 5]

// flatMap() - map + flat(1)
const sentences = ['Hello World', 'How are you'];
const words = sentences.flatMap((sentence) => sentence.split(' '));
console.log(words); // ['Hello', 'World', 'How', 'are', 'you']

// Filtering with flatMap
const numbers = [1, 2, 3, 4, 5];
const evenDoubled = numbers.flatMap((n) => (n % 2 === 0 ? [n * 2] : []));
console.log(evenDoubled); // [4, 8]

Sorting and Reversing

sort()

// Default sort (alphabetical)
const fruits = ['banana', 'apple', 'cherry'];
fruits.sort();
console.log(fruits); // ['apple', 'banana', 'cherry']

// Number sorting (incorrect without compare function)
const numbers = [10, 5, 40, 25, 1000, 1];
numbers.sort();
console.log(numbers); // [1, 10, 1000, 25, 40, 5] (alphabetical!)

// Correct number sorting
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 5, 10, 25, 40, 1000]

// Descending order
numbers.sort((a, b) => b - a);
console.log(numbers); // [1000, 40, 25, 10, 5, 1]

// Object sorting
const users = [
  { name: 'John', age: 30 },
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 35 },
];

users.sort((a, b) => a.age - b.age);
console.log(users); // Sorted by age

// Stable sort (ES2019+)
const items = [
  { name: 'A', value: 1 },
  { name: 'B', value: 1 },
  { name: 'C', value: 2 },
];

items.sort((a, b) => a.value - b.value);
// Order of A and B is preserved

reverse()

const arr = [1, 2, 3, 4, 5];

// Mutates original array
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1]

// To avoid mutation
const original = [1, 2, 3];
const reversed = [...original].reverse();
console.log(original); // [1, 2, 3]
console.log(reversed); // [3, 2, 1]

toSorted() and toReversed() (ES2023)

const numbers = [3, 1, 4, 1, 5];

// toSorted() - returns new sorted array
const sorted = numbers.toSorted();
console.log(numbers); // [3, 1, 4, 1, 5] (unchanged)
console.log(sorted); // [1, 1, 3, 4, 5]

// toReversed() - returns new reversed array
const reversed = numbers.toReversed();
console.log(numbers); // [3, 1, 4, 1, 5] (unchanged)
console.log(reversed); // [5, 1, 4, 1, 3]

Copying and Combining Arrays

concat()

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];

// Combining arrays
const combined = arr1.concat(arr2, arr3);
console.log(combined); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

// With individual values
const withValues = arr1.concat(4, 5, [6, 7]);
console.log(withValues); // [1, 2, 3, 4, 5, 6, 7]

// Shallow copy
const nested = [[1]];
const concatenated = nested.concat([[2]]);
nested[0].push(2);
console.log(concatenated); // [[1, 2], [2]] (affected by mutation)

slice()

const arr = ['a', 'b', 'c', 'd', 'e'];

// Extract portion
console.log(arr.slice(1, 4)); // ['b', 'c', 'd']
console.log(arr.slice(2)); // ['c', 'd', 'e']
console.log(arr.slice(-2)); // ['d', 'e']
console.log(arr.slice(1, -1)); // ['b', 'c', 'd']

// Copy entire array
const copy = arr.slice();
console.log(copy); // ['a', 'b', 'c', 'd', 'e']

// Shallow copy warning
const objects = [{ a: 1 }, { b: 2 }];
const sliced = objects.slice();
objects[0].a = 999;
console.log(sliced[0]); // { a: 999 } (affected!)

Spread Operator

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// Combining arrays
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]

// Copying array
const copy = [...arr1];
console.log(copy); // [1, 2, 3]

// With additional elements
const extended = [0, ...arr1, 3.5, ...arr2, 7];
console.log(extended); // [0, 1, 2, 3, 3.5, 4, 5, 6, 7]

Converting Arrays

join()

const arr = ['Hello', 'World'];

console.log(arr.join()); // 'Hello,World' (default comma)
console.log(arr.join(' ')); // 'Hello World'
console.log(arr.join('-')); // 'Hello-World'
console.log(arr.join('')); // 'HelloWorld'

// With numbers
const numbers = [1, 2, 3];
console.log(numbers.join(' + ')); // '1 + 2 + 3'

// Empty elements
const sparse = [1, , 3];
console.log(sparse.join('-')); // '1--3'

toString() and toLocaleString()

const arr = [1, 2, 3];
console.log(arr.toString()); // '1,2,3'

const mixed = [1, 'two', true, null, undefined];
console.log(mixed.toString()); // '1,two,true,,'

// toLocaleString()
const numbers = [1234.5, 6789.1];
console.log(numbers.toLocaleString('en-US')); // '1,234.5,6,789.1'
console.log(numbers.toLocaleString('de-DE')); // '1.234,5.6.789,1'

const dates = [new Date()];
console.log(dates.toLocaleString()); // Locale-specific date format

Array-like Methods

keys(), values(), and entries()

const arr = ['a', 'b', 'c'];

// keys() - returns iterator of indices
for (const key of arr.keys()) {
  console.log(key); // 0, 1, 2
}

// values() - returns iterator of values
for (const value of arr.values()) {
  console.log(value); // 'a', 'b', 'c'
}

// entries() - returns iterator of [index, value] pairs
for (const [index, value] of arr.entries()) {
  console.log(`${index}: ${value}`);
}
// 0: a
// 1: b
// 2: c

// Convert to array
console.log([...arr.keys()]); // [0, 1, 2]
console.log([...arr.values()]); // ['a', 'b', 'c']
console.log([...arr.entries()]); // [[0, 'a'], [1, 'b'], [2, 'c']]

Modern Array Methods

at()

const arr = ['a', 'b', 'c', 'd'];

// Positive indices
console.log(arr.at(0)); // 'a'
console.log(arr.at(2)); // 'c'

// Negative indices
console.log(arr.at(-1)); // 'd'
console.log(arr.at(-2)); // 'c'

// Out of bounds
console.log(arr.at(10)); // undefined
console.log(arr.at(-10)); // undefined

// vs bracket notation
console.log(arr[-1]); // undefined (doesn't work)
console.log(arr.at(-1)); // 'd' (works!)

with() (ES2023)

const arr = [1, 2, 3, 4, 5];

// with() - returns new array with element replaced
const updated = arr.with(2, 99);
console.log(arr); // [1, 2, 3, 4, 5] (unchanged)
console.log(updated); // [1, 2, 99, 4, 5]

// Negative indices
const lastUpdated = arr.with(-1, 100);
console.log(lastUpdated); // [1, 2, 3, 4, 100]

toSpliced() (ES2023)

const arr = ['a', 'b', 'c', 'd', 'e'];

// toSpliced() - returns new array with splice applied
const removed = arr.toSpliced(1, 2);
console.log(arr); // ['a', 'b', 'c', 'd', 'e'] (unchanged)
console.log(removed); // ['a', 'd', 'e']

const inserted = arr.toSpliced(2, 0, 'X', 'Y');
console.log(inserted); // ['a', 'b', 'X', 'Y', 'c', 'd', 'e']

Practical Examples

Remove Duplicates

const numbers = [1, 2, 2, 3, 4, 4, 5];

// Using Set
const unique1 = [...new Set(numbers)];
console.log(unique1); // [1, 2, 3, 4, 5]

// Using filter with indexOf
const unique2 = numbers.filter(
  (item, index) => numbers.indexOf(item) === index
);
console.log(unique2); // [1, 2, 3, 4, 5]

// Using reduce
const unique3 = numbers.reduce(
  (acc, num) => (acc.includes(num) ? acc : [...acc, num]),
  []
);
console.log(unique3); // [1, 2, 3, 4, 5]

Array Intersection and Union

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [4, 5, 6, 7, 8];

// Intersection
const intersection = arr1.filter((x) => arr2.includes(x));
console.log(intersection); // [4, 5]

// Union
const union = [...new Set([...arr1, ...arr2])];
console.log(union); // [1, 2, 3, 4, 5, 6, 7, 8]

// Difference (arr1 - arr2)
const difference = arr1.filter((x) => !arr2.includes(x));
console.log(difference); // [1, 2, 3]

Group By (Manual Implementation)

const people = [
  { name: 'Alice', age: 25, city: 'NYC' },
  { name: 'Bob', age: 30, city: 'LA' },
  { name: 'Charlie', age: 25, city: 'NYC' },
  { name: 'David', age: 30, city: 'Chicago' },
];

// Group by age
const groupByAge = people.reduce((groups, person) => {
  const age = person.age;
  groups[age] = groups[age] || [];
  groups[age].push(person);
  return groups;
}, {});

console.log(groupByAge);
// { 25: [Alice, Charlie], 30: [Bob, David] }

// Generic groupBy function
function groupBy(array, key) {
  return array.reduce((groups, item) => {
    const group = item[key];
    groups[group] = groups[group] || [];
    groups[group].push(item);
    return groups;
  }, {});
}

console.log(groupBy(people, 'city'));

Performance Considerations

  1. Mutation vs Immutability: Methods like sort() and reverse() mutate the original array
  2. Method Chaining: Can be elegant but creates intermediate arrays
  3. Large Arrays: Consider using for loops for better performance
  4. Sparse Arrays: Be aware of how different methods handle empty slots
  5. Memory Usage: Methods like map() and filter() create new arrays

Conclusion

JavaScript arrays provide a rich set of methods for every data manipulation need. Understanding when and how to use each method is crucial for writing efficient and maintainable code. Practice combining these methods to solve complex problems elegantly.