Back to Tutorials
📚 Beginner

Working with Arrays

7 min read | Arrays

Working with Arrays

Arrays are ordered collections of data — a shopping list, a set of scores, rows from a database. Almost every real program loops over, filters, or reshapes an array somewhere, so the methods in this tutorial are the ones you will use daily as a JavaScript developer.

Step 1: Creating Arrays

// Array literal — use this 99% of the time
const fruits = ["apple", "banana", "orange"];
// Array.from() builds an array from anything iterable
const chars = Array.from("hello"); // ["h", "e", "l", "l", "o"]
// Array.of() avoids the constructor's quirk
const nums = Array.of(3);          // [3]
const trap = new Array(3);         // [empty x 3] — three EMPTY slots, not [3]!

Why the literal is preferred: new Array(3) with a single number creates a sparse array of that length, not an array containing the number. The literal syntax has no such surprise, which is why style guides recommend it.

Step 2: Adding and Removing Elements

const arr = [1, 2, 3];
arr.push(4);      // [1, 2, 3, 4]  — add to end, returns new length
arr.pop();        // [1, 2, 3]     — remove from end, returns removed item
arr.unshift(0);   // [0, 1, 2, 3]  — add to start
arr.shift();      // [1, 2, 3]     — remove from start

Why it works with const: const arr locks the variable binding, not the array's contents, so mutating methods are fine. Also note that push/pop are fast, while shift/unshift must re-index every element — avoid them inside large loops.

Step 3: The Big Three — map, filter, reduce

These three methods replace most manual loops, and none of them modifies the original array:

const numbers = [1, 2, 3, 4, 5];
// map: transform EVERY element, same length out
const doubled = numbers.map(n => n * 2);        // [2, 4, 6, 8, 10]
// filter: keep elements that pass the test
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
// reduce: fold everything into ONE value
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15

Why it works: each method visits elements left to right and calls your function. map collects the return values into a new array; filter collects elements whose callback returned something truthy; reduce threads an accumulator through every call — acc starts at the second argument (0 here) and becomes whatever your callback returns each round. Forgetting that initial value is a classic bug: without it, reduce uses the first element as the accumulator, which breaks on empty arrays.

You can chain them, and the pipeline reads like a sentence:

const cart = [
  { name: "Pen", price: 2, qty: 3 },
  { name: "Book", price: 12, qty: 1 },
  { name: "Bag", price: 25, qty: 0 }
];
const total = cart
  .filter(item => item.qty > 0)
  .map(item => item.price * item.qty)
  .reduce((acc, n) => acc + n, 0);
console.log(total); // 18

Step 4: Finding Things

const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" }
];
users.find(u => u.id === 1);          // { id: 1, name: "Alice" }
users.findIndex(u => u.name === "Bob"); // 1
users.some(u => u.id > 1);            // true  — at least one matches?
users.every(u => u.id > 0);           // true  — do ALL match?
users.map(u => u.name).includes("Alice"); // true

find returns undefined when nothing matches — always handle that case before reading properties off the result.

Step 5: Copying and Combining with Spread

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
const copy = [...arr1];              // a NEW array with the same items

Why copying matters: const copy = arr1 does not copy anything — both names point at the same array, so changing one "changes" the other. Spread creates a genuinely new array. It is a shallow copy though: nested objects inside are still shared.

Common Beginner Errors and Fixes

  • Expecting map or filter to change the original array. They never do; they return a new one. Fix: assign the result — items = items.filter(...).
  • Returning nothing from a map callback when using { } braces: numbers.map(n => { n * 2 }) produces [undefined, undefined, ...]. Fix: add return, or drop the braces.
  • Using forEach and trying to collect results. forEach always returns undefined. Fix: use map when you need output.
  • Off-by-one on length: the last index is arr.length - 1, so arr[arr.length] is undefined. Fix: use arr.at(-1) for the last element.
  • Removing items while looping forward skips elements, because indexes shift underneath you. Fix: use filter to build the array you want instead of deleting in place.

Practice Exercise

You are given daily step counts: const steps = [4200, 11050, 8600, 300, 9999, 12480];

  • Build an array of only the days with at least 8000 steps.
  • Convert those qualifying days into kilometers (assume 1400 steps = 1 km, round with Math.round).
  • Compute the total kilometers with reduce.
  • Log the count of qualifying days and the total distance.
  • Expected output: 4 qualifying days, and a total of about 30 km. Try to write it as one filter → map → reduce chain — then try again with a single reduce and compare which version you find more readable.