Adding & Removing Array Elements
Learn how to add and remove elements from arrays using push(), pop(), shift(), unshift(), and splice() — including return values, performance, and common gotchas.
Reading Time
18 min
Lesson
Lesson 17 of 48
Introduction
JavaScript arrays are dynamic, which means you can grow or shrink them at any time — you never have to declare a fixed size up front. To do this, JavaScript gives you a handful of built-in methods. Some of these methods are "mutating": they change the original array in place and often return something small, like the new length or the removed item. Others are "non-mutating": they leave the original array untouched and return a brand new array instead. In this lesson we focus on the five classic mutating methods — push(), pop(), shift(), unshift(), and splice() — because understanding how they mutate the array is the key to avoiding subtle bugs later, especially in frameworks like React where mutating state directly can cause the UI not to update.
Methods Overview
| Method | Purpose | Modifies Original Array | Returns | Typical Speed |
|---|---|---|---|---|
| push() | Add element(s) to the end | ✅ Yes | New length | Fast — O(1) |
| pop() | Remove the last element | ✅ Yes | The removed element | Fast — O(1) |
| unshift() | Add element(s) to the beginning | ✅ Yes | New length | Slower — O(n) |
| shift() | Remove the first element | ✅ Yes | The removed element | Slower — O(n) |
| splice() | Add/remove/replace anywhere | ✅ Yes | Array of removed elements | Depends on position — O(n) |
push()
The push() method adds one or more elements to the end of an array and returns the new length of the array (not the array itself). Because it only touches the end of the array, the JavaScript engine doesn't need to shift any existing elements around, which is why push() is fast even on large arrays. You can pass multiple arguments to push() in a single call — e.g. fruits.push("Mango", "Kiwi") — and both will be appended in order. This makes push() the go-to method for building up a list incrementally, such as collecting results in a loop.
push() Example
Console Output
Click “Run” to see the console output here.
pop()
The pop() method removes the last element from an array and returns that removed element, so you can capture and use it right away. If the array is already empty, pop() does not throw an error — it simply returns undefined and leaves the array as an empty array. Because pop() only removes from the end, it is just as fast as push(), which is why the pair push()/pop() is the standard way to implement a "stack" data structure (last in, first out).
pop() Example
Console Output
Click “Run” to see the console output here.
unshift()
The unshift() method adds one or more elements to the very beginning of an array and, like push(), returns the new length. The tradeoff is performance: because every existing element has to be shifted one position to the right to make room, unshift() takes longer as the array grows — this is known as O(n) time complexity. For small arrays this difference is unnoticeable, but it's worth knowing if you're repeatedly unshifting into a very large array in a performance-sensitive loop.
unshift() Example
Console Output
Click “Run” to see the console output here.
shift()
The shift() method removes the first element from an array and returns it, shifting every remaining element one position to the left to close the gap. Just like unshift(), this re-indexing means shift() is an O(n) operation — slower than pop() on large arrays. shift() and push() together are commonly used to implement a "queue" data structure (first in, first out), such as processing items in the order they arrived.
shift() Example
Console Output
Click “Run” to see the console output here.
splice()
The splice() method is the most flexible of the five: it can remove elements, insert elements, or do both at the same time, at any position in the array. Its signature is array.splice(start, deleteCount, item1, item2, ...). The "start" argument is the index to begin at (negative values count from the end), "deleteCount" is how many elements to remove from that point, and any further arguments are new elements to insert at that same position. splice() always returns an array containing whatever elements were removed — this is different from push()/pop()/shift()/unshift(), which return either a length or a single value.
Remove Elements using splice()
Console Output
Click “Run” to see the console output here.
Add Elements using splice()
Console Output
Click “Run” to see the console output here.
Replace Elements using splice()
Console Output
Click “Run” to see the console output here.
splice() with a negative start index
Console Output
Click “Run” to see the console output here.
When to Use Which Method
Use push() and pop() for stack-like behavior (last in, first out) and when you mainly add/remove at the end — they're the fastest of the group. Use shift() and unshift() for queue-like behavior (first in, first out), keeping in mind they are slower on large arrays because every element has to be re-indexed. Use splice() whenever you need to insert, remove, or replace elements at a specific index rather than just at the start or end — it's more powerful, but also easy to misuse if you forget what the second argument (deleteCount) does.
Important
All five of these methods mutate — that is, change — the original array rather than returning a new one. This matters a lot in situations like React state, where the framework expects you to treat state as immutable and create a new array instead of mutating the existing one. If you want to keep the original array unchanged, avoid these methods and instead use non-mutating alternatives like slice() (not splice!), concat(), the spread operator [...arr], or newer immutable methods such as toSorted(), toSpliced(), and toReversed() introduced in modern JavaScript (ES2023).