Historical Context & Motivation
Before programming languages offered built-in array methods, developers had to write low-level code to manually shift memory around whenever they wanted to add or remove an item from a list. This was tedious, error-prone, and slowed down development significantly. Early languages like C required programmers to track the size of their arrays by hand and use loops to move elements one by one.
JavaScript changed this by shipping with a set of convenient, built-in methods right on the Array object. These methods let you modify arrays with a single function call instead of writing manual loops. Understanding this evolution helps you appreciate why methods like push, pop, splice, and slice exist—they solve real problems that plagued programmers for decades.
push, pop, shift, unshift, splice, and slice.forEach, map, and filter, all of which build on the foundation of the original mutation methods....) and destructuring offer new ways to work with arrays, but the classic methods remain the backbone of array manipulation.The central question these methods answer is straightforward: how do you efficiently add, remove, or extract elements from an array without writing loops every time? Let's dive into the principles behind each method.
Core Principles & Definitions
JavaScript arrays are ordered collections of values, and the six methods we are studying can be grouped by two key traits. First, does the method mutate (change) the original array, or does it return a new copy? Second, which end of the array does the method operate on—the beginning, the end, or somewhere in the middle? Keeping these two questions in mind will make every method feel intuitive.
Mutating vs. Non-Mutating
push, pop, shift, unshift, and splice change the original array in place. slice creates a brand-new array, leaving the original untouched.End Operations: push & pop
push adds one or more elements to the end of an array and returns the new length. pop removes and returns the last element. These are the fastest operations because no other elements need to move.Start Operations: unshift & shift
unshift adds elements to the beginning; shift removes the first element. Every remaining element must be re-indexed, making these slower on large arrays.Middle Operations: splice
splice(start, deleteCount, ...items) is the Swiss-army knife. It can insert, remove, or replace elements at any position. It mutates the original and returns an array of the removed elements.Copying a Portion: slice
slice(start, end) extracts a shallow copy from start up to (but not including) end. The original array is never modified, which makes it safe for read-only operations.Visual Explanation — push, pop, shift, unshift
The diagram below shows a five-element array and illustrates how each of the four basic methods operates on it. Pay attention to which end of the array each method targets, and notice which methods return the removed element versus the new array length.
["A", "B", "C", "D"] array. Solid colored blocks are elements that remain; dashed outlines indicate removed elements. New additions are highlighted with bold borders.Notice a pattern: push and pop work on the right side (end) of the array, while unshift and shift work on the left side (beginning). The methods that add elements (push and unshift) return the new length of the array, while the methods that remove elements (pop and shift) return the element that was taken out.
How Each Method Works Under the Hood
Each of these six methods has a specific signature (the parameters it accepts) and a specific return value (what it gives back). Understanding these signatures is the key to using the methods confidently.
push and pop
length of the array (a number).undefined.unshift and shift
length.undefined if the array is empty.splice and slice
start — index to begin changes. deleteCount — number of elements to remove. Remaining arguments are inserted at start. Returns an array of removed elements. Mutates the original array.start up to (but not including) end. Negative indices count backwards from the end. Does NOT mutate the original.splice and slice. Remember: splice changes the array (mutates it). slice copies a portion without changing anything.splice and slice — Detailed Breakdown
While push/pop/shift/unshift each do one specific thing, splice is far more flexible. Depending on how you call it, splice can delete elements, insert elements, or do both at once. Meanwhile, slice is your go-to for extracting a subsection without disturbing the original.
splice(1, 2) removes two elements, splice(2, 1, "kiwi", "mango") replaces one and inserts two, and slice(1, 4) copies a sub-range without modifying the original.The splice examples above show two common use cases. In the first, we only supplied start and deleteCount, so it purely deleted elements. In the second, we also passed replacement items after deleteCount, so it removed one element and inserted two new ones at the same position. Meanwhile, slice selected indices 1 through 3 (remember, the end index is exclusive) and returned a fresh array. The original stayed perfectly intact.
splice and slice accept negative indices. For example, slice(-2) returns the last two elements, because −2 counts backwards from the end. This is handy when you don't know the exact length of the array.Worked Example — Building a Playlist
Let's walk through a realistic scenario. Imagine you're building a music playlist app and you need to manage an array of song titles using the methods we've learned.
let playlist = ["Bohemian Rhapsody", "Imagine", "Stairway to Heaven"];["Bohemian Rhapsody", "Imagine", "Stairway to Heaven"] (length: 3)playlist.push("Blinding Lights"); The method returns 4 (the new length).["Bohemian Rhapsody", "Imagine", "Stairway to Heaven", "Blinding Lights"]playlist.unshift("Levitating"); Returns 5. Every other song shifts one index higher.["Levitating", "Bohemian Rhapsody", "Imagine", "Stairway to Heaven", "Blinding Lights"]let removed = playlist.pop(); Now removed holds "Blinding Lights".["Levitating", "Bohemian Rhapsody", "Imagine", "Stairway to Heaven"]playlist.splice(2, 1, "Hotel California"); This removes 1 element at index 2 and inserts the new song. The return value is ["Imagine"].["Levitating", "Bohemian Rhapsody", "Hotel California", "Stairway to Heaven"]let shared = playlist.slice(1, 3); This copies indices 1 and 2 into a new array. The original playlist remains unchanged.["Bohemian Rhapsody", "Hotel California"] | original playlist is untouchedMethod Comparison — Strengths & Limitations
Now that you've seen every method in action, let's organize them side by side. The table below compares each method on four key dimensions: what it does, where it operates, whether it mutates the original, and what it returns.
| Method | Action | Position | Mutates? | Returns |
|---|---|---|---|---|
push() | Add element(s) | End | Yes | New length |
pop() | Remove element | End | Yes | Removed element |
unshift() | Add element(s) | Beginning | Yes | New length |
shift() | Remove element | Beginning | Yes | Removed element |
splice() | Add / Remove / Replace | Any position | Yes | Array of removed items |
slice() | Copy a range | Any range | No | New array (copy) |
push, pop, shift, unshift, splice). If you need a copy without altering the source data—for instance, when displaying a filtered view while keeping the original data intact—reach for slice. Choosing the right method is like choosing the right tool from a toolbox: a hammer works great for nails, but you wouldn't use it to measure a board.Connection to Advanced Array Concepts
The six methods you've learned form the foundation for more advanced array techniques. As you progress in JavaScript, you'll encounter higher-order methods like map, filter, and reduce that accept callback functions and build on the same principles of iteration and transformation. You'll also encounter the spread operator (...) which provides a concise, non-mutating alternative to many of these operations.
| Basic Method (This Lesson) | Advanced Alternative | Key Difference |
|---|---|---|
push(item) | [...arr, item] | Spread creates a new array instead of mutating |
unshift(item) | [item, ...arr] | Non-mutating; useful in React state updates |
splice() (remove) | arr.filter() | filter returns a new array matching a condition |
slice() | arr.toSpliced() (ES2023) | toSpliced combines splice behavior with non-mutation |
In frameworks like React, Vue, and Angular, avoiding mutation is often preferred because it makes it easier to track changes. That's why understanding the distinction between mutating methods and non-mutating methods now will pay dividends when you start building interactive web applications. Mastering the basics covered in this lesson gives you the vocabulary and mental model to learn these advanced patterns much faster.
Practice Problems
splice and slice. Which one mutates the original array, and which one does not?let colors = ["red", "green", "blue"];, what is the value of colors and the return value after running colors.push("yellow", "purple");?let nums = [10, 20, 30, 40, 50];, write the code to replace the element 30 with 35 and 37 using splice. What does the array look like after, and what does splice return?let tasks = ["Email boss", "Buy groceries", "Walk dog", "Study JS"]; They complete "Buy groceries" (index 1) and want it removed. They also want to add "Call doctor" to the very front as a high priority. Write the code using splice and unshift, and show the final array.original to remain unchanged:
let original = [1, 2, 3, 4, 5];
let copy = original;
copy.splice(0, 2);
However, when they log original, it shows [3, 4, 5]. Explain why this happened and how to fix it using one of the methods from this lesson.Lesson Summary
JavaScript provides six essential methods for manipulating arrays. push adds elements to the end and returns the new length, while pop removes and returns the last element. unshift adds elements to the beginning and returns the new length, while shift removes and returns the first element. All four of these are mutating methods that change the original array.
For more complex operations, splice can insert, remove, or replace elements at any index and also mutates the original array. In contrast, slice is the only non-mutating method of the six—it returns a shallow copy of a portion of the array without altering the source. Remember: understanding mutation is critical because it affects how data flows through your programs and sets you up for success with advanced topics like immutable state management in modern frameworks.