Advanced30 min read

Modern Array Methods

Master map, filter, reduce, find, some, every, and other functional array methods for clean, expressive code.

Transforming: map()

The map() method creates a new array by applying a function to every element of the original array. It does not mutate the original.

javascript
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
console.log(doubled);  // [2, 4, 6, 8, 10]
console.log(numbers);  // [1, 2, 3, 4, 5] — unchanged

map() always returns an array of the same length as the original. It is the go-to method for transforming data:

javascript
// Extract a property from objects
const users = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
];
const names = users.map(user => user.name);
// ['Alice', 'Bob']

// Convert types
const strings = ['1', '2', '3'];
const nums = strings.map(Number);
// [1, 2, 3]

// Build HTML
const items = ['Apple', 'Banana', 'Cherry'];
const html = items.map(item => `<li>${item}</li>`).join('');
// '<li>Apple</li><li>Banana</li><li>Cherry</li>'

The callback receives three arguments: (element, index, array). The index and array arguments are optional but useful:

javascript
const indexed = ['a', 'b', 'c'].map((letter, i) => `${i}: ${letter}`);
// ['0: a', '1: b', '2: c']

Filtering: filter() & find()

filter() returns a new array containing only the elements that pass a condition (the callback returns true):

javascript
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]

The returned array may be shorter than the original (or even empty if nothing matches). The original is not mutated.

javascript
const users = [
  { name: 'Alice', active: true },
  { name: 'Bob', active: false },
  { name: 'Charlie', active: true },
];
const activeUsers = users.filter(u => u.active);
// [{ name: 'Alice', active: true }, { name: 'Charlie', active: true }]

find() returns the first element that matches the condition (or undefined if none match):

javascript
const found = numbers.find(n => n > 5);
console.log(found); // 6 (the first number greater than 5)

findIndex() returns the index of the first match (or -1 if not found):

javascript
const index = numbers.findIndex(n => n > 5);
console.log(index); // 5

includes() is the simplest check — returns true or false for a specific value:

javascript
console.log(numbers.includes(3)); // true
console.log(numbers.includes(99)); // false

Reducing: reduce()

reduce() processes an array and reduces it to a single value. It takes a callback with two main parameters — an accumulator and the current element — plus an initial value:

javascript
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, current) => {
  return accumulator + current;
}, 0);
console.log(sum); // 15

Step by step:

  • Start: accumulator = 0 (initial value)
  • Iteration 1: 0 + 1 = 1
  • Iteration 2: 1 + 2 = 3
  • Iteration 3: 3 + 3 = 6
  • Iteration 4: 6 + 4 = 10
  • Iteration 5: 10 + 5 = 15

reduce() is extremely versatile:

javascript
// Counting occurrences
const fruits = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple'];
const counts = fruits.reduce((acc, fruit) => {
  acc[fruit] = (acc[fruit] || 0) + 1;
  return acc;
}, {});
// { apple: 3, banana: 2, cherry: 1 }

// Finding max value
const max = numbers.reduce((a, b) => a > b ? a : b);
// 5

// Flattening arrays
const nested = [[1, 2], [3, 4], [5, 6]];
const flat = nested.reduce((acc, arr) => [...acc, ...arr], []);
// [1, 2, 3, 4, 5, 6]

Always provide an initial value (the second argument to reduce). Omitting it uses the first element as the initial accumulator, which can cause bugs with empty arrays.

Testing: some() & every()

some() returns true if at least one element passes the test:

javascript
const numbers = [1, 3, 5, 7, 8];
console.log(numbers.some(n => n % 2 === 0)); // true (8 is even)
console.log(numbers.some(n => n > 10));      // false

every() returns true if all elements pass the test:

javascript
const scores = [80, 92, 75, 88];
console.log(scores.every(s => s >= 70)); // true (all passed)
console.log(scores.every(s => s >= 80)); // false (75 < 80)

Both methods short-circuit — they stop iterating as soon as the result is determined. some() stops at the first true, and every() stops at the first false.

flat() flattens nested arrays by one level (or more with a depth argument):

javascript
const nested = [[1, 2], [3, [4, 5]]];
console.log(nested.flat());  // [1, 2, 3, [4, 5]]
console.log(nested.flat(2)); // [1, 2, 3, 4, 5]

flatMap() combines map() and flat(1) in a single step:

javascript
const sentences = ['Hello world', 'Goodbye world'];
const words = sentences.flatMap(s => s.split(' '));
// ['Hello', 'world', 'Goodbye', 'world']

Chaining Methods

Since map(), filter(), and many other array methods return new arrays, you can chain them together for concise, readable data transformations:

javascript
const users = [
  { name: 'Alice', age: 30, active: true },
  { name: 'Bob', age: 17, active: true },
  { name: 'Charlie', age: 25, active: false },
  { name: 'Diana', age: 22, active: true },
];

const result = users
  .filter(u => u.active)           // keep active users
  .filter(u => u.age >= 18)        // keep adults
  .map(u => u.name)                // extract names
  .join(', ');                     // combine into string

console.log(result); // 'Alice, Diana'

Chaining reads like a pipeline — each step transforms the data and passes it to the next. This is a core pattern in functional programming.

You can also chain into a reduce():

javascript
const total = orders
  .filter(order => order.status === 'completed')
  .map(order => order.total)
  .reduce((sum, total) => sum + total, 0);

Tip: For very large arrays, each chained method creates a new intermediate array. If performance is critical, a single reduce() or a for loop may be more efficient. But for most use cases, the readability of chaining far outweighs the performance cost.

Array Methods in Action

html
<div id="output"></div>

<script>
  const products = [
    { name: 'Laptop', price: 999, inStock: true },
    { name: 'Phone', price: 699, inStock: true },
    { name: 'Tablet', price: 499, inStock: false },
    { name: 'Watch', price: 299, inStock: true },
    { name: 'Earbuds', price: 149, inStock: true },
  ];

  // Chain: filter in-stock → map to formatted strings → join
  const available = products
    .filter(p => p.inStock)
    .map(p => `${p.name}: $${p.price}`)
    .join(', ');

  // Reduce: total of in-stock items
  const total = products
    .filter(p => p.inStock)
    .reduce((sum, p) => sum + p.price, 0);

  const output = document.getElementById('output');
  output.innerHTML = `
    <p><strong>Available:</strong> ${available}</p>
    <p><strong>Total value:</strong> $${total}</p>
  `;
</script>

What does [1, 2, 3].map(x => x * 2) return?

Ready to practice?

Create your free account to access the interactive code editor, run challenges, and track your progress.