
A practical guide to six essential JavaScript array methods that every developer uses daily, explained from scratch with real examples, comparisons to traditional loops, and a hands-on assignment to cement your understanding.
Think of an array like a row of lockers. Each locker holds something, and you need to do things with those items: pick some out, transform them, or count them up. JavaScript gives you built-in tools to do exactly that, and using the right tool for the job is what separates clean code from a mess of for loops.
This post covers six array methods that you will use in nearly every JavaScript project. If you are just starting out, go slow, try each example in your browser console, and watch what happens. If you are already comfortable with these, stick around. There is some depth here worth revisiting.
Picture a stack of plates. You put new plates on top, and when you take one, you take from the top too. That is exactly how push() and pop() work.
push() adds one or more elements to the end of an array and returns the new length.
pop() removes the last element and returns it.
Before push(): [1, 2, 3] After push(4): [1, 2, 3, 4] ^-- added here Before pop(): [1, 2, 3, 4] After pop(): [1, 2, 3] ^-- removed from here
javascriptconst fruits = ["apple", "banana"]; fruits.push("mango"); console.log(fruits); // ["apple", "banana", "mango"] const removed = fruits.pop(); console.log(removed); // "mango" console.log(fruits); // ["apple", "banana"]
Try it yourself: Open your browser console (F12 or right-click > Inspect > Console) and paste this in. Watch the array change.
One thing to know: push() mutates the original array. It does not return a new array. Same with pop(). These methods change the array in place, which matters when you care about immutability (React devs, take note).
Same idea as push/pop, just from the opposite end. Think of a queue at a coffee shop. New people join at the back (push), and the person at the front gets served first (shift).
unshift() adds elements to the beginning of the array.
shift() removes the first element and returns it.
Before unshift(0): [1, 2, 3] After unshift(0): [0, 1, 2, 3] ^-- added here Before shift(): [0, 1, 2, 3] After shift(): [1, 2, 3] ^-- removed from here
javascriptLoading syntax highlighter...
A heads-up for intermediate devs: shift() and unshift() are slower than push() and pop() on large arrays. When you remove or add from the beginning, JavaScript has to re-index every element. For most real-world usage, this does not matter. But if you are working with thousands of items in a performance-critical loop, reach for a different data structure.
Here is where things get more interesting. map() goes through every item in an array, runs a function on it, and returns a brand new array with the results. The original array stays untouched.
Think of it like a conveyor belt in a factory. Each product goes in, gets modified, and comes out the other side. The line never stops, every item gets processed.
Original: [1, 2, 3, 4] | | | | x2 x2 x2 x2 | | | | Result: [2, 4, 6, 8]
javascriptconst numbers = [1, 2, 3, 4]; // Traditional for loop const doubled = []; for (let i = 0; i < numbers.length; i++) { doubled.push(numbers[i] * 2); } // Using map() const doubledWithMap = numbers.map((num) => num * 2); console.log(doubledWithMap); // [2, 4, 6, 8]
The map() version is shorter, but more importantly, it is expressive. You are declaring what you want, not how to do it step by step. That is the functional programming mindset, and it makes code easier to read and reason about.
map() always returns an array of the same length as the original. Every element gets transformed, no exceptions. If you want to skip some elements, that is what filter() is for.
filter() goes through an array and returns a new array with only the elements that pass a test. You give it a function that returns true or false for each item. True means keep it, false means skip it.
Original: [3, 8, 1, 12, 5, 15] | | | | | | >5? >5? >5? >5? >5? >5? N Y N Y N Y | | | Result: [8, 12, 15]
javascriptconst numbers = [3, 8, 1, 12, 5, 15]; // Traditional for loop const bigNumbers = []; for (let i = 0; i < numbers.length; i++) { if (numbers[i] > 5) { bigNumbers.push(numbers[i]); } } // Using filter() const bigNumbersWithFilter = numbers.filter((num) => num > 5); console.log(bigNumbersWithFilter); // [8, 12, 15]
The original numbers array is unchanged. filter() gives you a new array, shorter than or equal to the original in length. If nothing passes the test, you get an empty array back, not null, not an error.
A common pattern you will see in React is filtering a list of items based on user input, like a search box. The entire list lives in state, and you filter() it before rendering. No mutations, no side effects.
reduce() gets a reputation for being confusing, and honestly, that reputation is a bit earned. But the core idea is simple.
Think of reduce as a running total. You start with a starting value (called the accumulator), and for each item in the array, you update that total. At the end, you have one final result.
Array: [1, 2, 3, 4] | | | | Start: 0 0+1 = 1 1+2 = 3 3+3 = 6 6+4 = 10 Result: 10
javascriptconst numbers = [1, 2, 3, 4]; const total = numbers.reduce((accumulator, currentValue) => { return accumulator + currentValue; }, 0); console.log(total); // 10
The reduce() function takes two arguments: the callback function and the initial value (0 in this case). The callback receives the accumulator (the running total so far) and the current element being processed.
Start with this mental model: accumulator is your running total, and you update it on every step. Once you are comfortable with that, you can use reduce() for a lot more than just summing numbers, but that comes later. For now, sum of an array is the perfect starting point.
forEach() is the closest thing to a traditional for loop in the array methods world. It runs a function for each element, one by one. The key difference: it does not return anything. You use it when you want to do something with each item, not when you need a result back.
javascriptconst colors = ["red", "green", "blue"]; // Traditional for loop for (let i = 0; i < colors.length; i++) { console.log(colors[i]); } // Using forEach() colors.forEach((color) => { console.log(color); }); // Both output: // red // green // blue
Use forEach() when you are doing side effects, like logging, updating something external, or triggering an API call for each item. If you need a transformed or filtered array back, reach for map() or filter() instead.
One thing to know: you cannot break out of a forEach() loop like you can with a regular for loop. If you need early exit, use a for loop or Array.prototype.some().
+------------------+---------------------------+-------------------+ | Method | What it does | Returns | +------------------+---------------------------+-------------------+ | push() | Add to end | New length | | pop() | Remove from end | Removed element | | unshift() | Add to beginning | New length | | shift() | Remove from beginning | Removed element | | map() | Transform every element | New array | | filter() | Keep elements that pass | New array | | reduce() | Collapse to single value | Single value | | forEach() | Run fn for each element | undefined | +------------------+---------------------------+-------------------+
Here is a small challenge to practice everything in one go. Try this in your browser console:
javascriptLoading syntax highlighter...
Each step uses only one method, so you can see exactly what each one does to the data. Once this feels natural, you can start chaining them, but getting comfortable with each method on its own first is the right approach.
push/pop work at the end of an array, shift/unshift work at the beginning. All four mutate the original array.map() transforms every element and always gives back an array of the same length.filter() gives back a subset of the array based on a condition.reduce() collapses an array into a single value using an accumulator.forEach() is for side effects. It does not return a new array.Open the console. Break things. Try variations. That is the fastest path from understanding to fluency.
Related posts based on tags, category, and projects
Arrays are one of the first data structures you'll use in JavaScript, and they're more powerful than they look. This post covers everything from creating your first array to looping through it, with the kind of depth that makes it click.
Variables are the foundation of every JavaScript program they let you store, label, and reuse data. This post walks you through what variables are, how to declare them, the seven primitive data types, and the three non-primitive types: objects, arrays, and functions.
`this` is one of JavaScript's most misunderstood keywords, and Node.js adds its own twists on top. This post breaks down exactly how `this` behaves in every context you'll encounter, why `globalThis` exists, and the subtle gotchas that catch even experienced developers off guard.
Node.js is more than just "JavaScript on the server." It's a carefully assembled runtime built on top of battle-tested components that make non-blocking I/O possible. This post breaks down how those components fit together, what they actually do, and why the design choices matter.
const queue = ["Alice", "Bob", "Charlie"];
queue.unshift("Zara"); // Zara cuts to the front
console.log(queue); // ["Zara", "Alice", "Bob", "Charlie"]
const served = queue.shift(); // First person served
console.log(served); // "Zara"
console.log(queue); // ["Alice", "Bob", "Charlie"]// Step 1: Create your array
const numbers = [3, 7, 2, 14, 9, 21, 5, 18];
// Step 2: Double every number using map()
const doubled = numbers.map((num) => num * 2);
console.log("Doubled:", doubled);
// [6, 14, 4, 28, 18, 42, 10, 36]
// Step 3: Filter numbers greater than 10 from the doubled array
const greaterThanTen = doubled.filter((num) => num > 10);
console.log("Greater than 10:", greaterThanTen);
// [14, 28, 18, 42, 36]
// Step 4: Calculate the total sum using reduce()
const total = greaterThanTen.reduce((acc, num) => acc + num, 0);
console.log("Total sum:", total);
// 138