Question
I need to add, or prepend, an element to the beginning of a JavaScript array.
For example, if the array is:
[23, 45, 12, 67]
and the response from an AJAX call is 34, I want the updated array to become:
[34, 23, 45, 12, 67]
Right now, I am considering this approach:
var newArray = [];
newArray.push(response);
for (var i = 0; i < theArray.length; i++) {
newArray.push(theArray[i]);
}
theArray = newArray;
Is there a better way to do this? Does JavaScript provide a built-in method for adding elements to the beginning of an array?
Also, since my current approach is O(n), I would be interested in understanding whether there are better implementations and what their trade-offs are.
Short Answer
By the end of this page, you will understand how to add elements to the beginning of a JavaScript array, when to use unshift(), how it compares with alternatives like spread syntax and concat(), and why prepending to arrays usually remains an O(n) operation.
Concept
In JavaScript, arrays have built-in methods for adding and removing elements. When you want to place a new value at the start of an array, the standard built-in method is unshift().
const arr = [23, 45, 12, 67];
arr.unshift(34);
console.log(arr); // [34, 23, 45, 12, 67]
This matters because adding to the beginning of an array is a very common operation in real applications:
- showing newest notifications first
- adding recent messages to a feed
- maintaining a list of latest results
- inserting priority items at the front
However, there is an important performance idea behind this: JavaScript arrays are index-based. If you insert an item at index 0, the existing items usually need to shift one position to the right.
For example:
23moves from index0to145moves from index1to212moves from index2to367moves from index3to4
That is why prepending is typically O(n). Your manual loop is also O(n), and so is unshift() in the general case. The main improvement from using unshift() is clarity, correctness, and convenience, not a lower time complexity.
If you need a new array without mutating the original one, you can also use:
const newArr = [34, ...arr];
or:
const newArr = [34].concat(arr);
So the key idea is:
- use
unshift()when you want to modify the existing array - use spread syntax or
concat()when you want a new array - expect prepending to still be
O(n)for normal arrays
Mental Model
Think of a JavaScript array like a row of numbered lockers:
- locker
0contains23 - locker
1contains45 - locker
2contains12 - locker
3contains67
If you want to put 34 into locker 0, the current contents cannot stay where they are. Every existing item must move one locker to the right.
So prepending is like inserting a new person at the front of a line: everyone already in line has to step back one position.
That is why adding at the beginning is more work than adding at the end. Appending with push() is usually easier because no existing elements need to move.
Syntax and Examples
The most direct built-in method is unshift().
array.unshift(element1, element2, ...)
It adds one or more elements to the beginning of an array and returns the new length.
Basic example
const numbers = [23, 45, 12, 67];
const newLength = numbers.unshift(34);
console.log(numbers); // [34, 23, 45, 12, 67]
console.log(newLength); // 5
Explanation:
unshift(34)inserts34at the start- the original array is modified
- the method returns the array's new length
Add multiple elements
const numbers = [23, 45, 12, 67];
numbers.unshift(1, 2, 3);
console.log(numbers); // [1, 2, 3, 23, 45, 12, 67]
Create a new array instead of mutating
Using spread syntax:
const original = [23, 45, 12, 67];
const updated = [34, ...original];
console.log(original); // [23, 45, 12, 67]
console.log(updated); // [34, 23, 45, 12, 67]
Using concat():
const original = [23, 45, 12, 67];
const updated = [34].concat(original);
console.log(updated); // [34, 23, 45, 12, 67]
Which one should beginners remember?
unshift()→ modify the existing array[value, ...array]→ create a new array[value].concat(array)→ older but still valid alternative
Step by Step Execution
Consider this example:
const arr = [23, 45, 12, 67];
arr.unshift(34);
console.log(arr);
Here is what happens step by step:
Step 1: Create the array
const arr = [23, 45, 12, 67];
Memory conceptually looks like this:
| Index | Value |
|---|---|
| 0 | 23 |
| 1 | 45 |
| 2 | 12 |
| 3 | 67 |
Step 2: Call unshift(34)
arr.unshift(34);
JavaScript inserts 34 at index 0.
To make room, the existing elements shift right:
67moves from3to412moves from2to345moves from1to223moves from0to134is placed at0
Now the array becomes:
| Index | Value |
|---|---|
| 0 | 34 |
| 1 | 23 |
| 2 | 45 |
| 3 | 12 |
| 4 | 67 |
Step 3: Print the result
console.log(arr);
Output:
[34, 23, 45, 12, 67]
Trace with return value
const arr = [23, 45, 12, 67];
const length = arr.unshift(34);
console.log(length); // 5
console.log(arr); // [34, 23, 45, 12, 67]
unshift() returns the new length, not the updated array.
Real World Use Cases
Prepending values to arrays appears in many common situations.
Activity feeds
A new notification arrives and should appear first:
const notifications = ["Older alert", "Yesterday's alert"];
notifications.unshift("New alert");
Chat applications
If messages are displayed with newest first, a newly received message may be inserted at the front:
const messages = ["How are you?", "Hello"];
messages.unshift("Latest message");
Search history
Recent searches are often shown first:
const searches = ["javascript map", "css grid"];
searches.unshift("array unshift");
Logging and monitoring dashboards
Incoming events may be added to the start of a list so the most recent issue is visible immediately.
Data processing scripts
You may prepend a header row or a high-priority item before processing a list.
const tasks = ["email report", "clean temp files"];
tasks.unshift("restart server");
Real Codebase Usage
In real projects, developers choose between mutating and non-mutating approaches depending on the situation.
1. Direct mutation with unshift()
Common in simple scripts or local state where changing the original array is fine.
queue.unshift(newItem);
Use this when:
- you own the array
- mutation is acceptable
- you want the simplest built-in method
2. Immutable update with spread syntax
Very common in React, Redux, and other state-management patterns.
const updatedItems = [newItem, ...items];
Use this when:
- you should not mutate existing state
- change detection depends on a new array reference
- you want predictable state updates
3. Guard clauses before prepending
Developers often validate data first.
if (response == null) {
return;
}
items.unshift(response);
This prevents invalid values from being inserted.
4. Keeping arrays limited in size
A common pattern is prepend, then trim.
logs.unshift(newLog);
if (logs.length > 100) {
logs.pop();
}
This keeps only the latest 100 entries.
5. Combining with API results
async function addLatestUser(users) {
const response = await fetch("/api/latest-user");
const user = await response.json();
users.unshift(user);
}
In codebases, the main decision is usually not whether unshift() exists, but whether the array should be mutated or copied.
Common Mistakes
Here are common beginner mistakes when adding elements to the beginning of an array.
Mistake 1: Expecting unshift() to return the array
Broken code:
const arr = [23, 45];
const result = arr.unshift(34);
console.log(result); // 3, not [34, 23, 45]
Why it happens:
unshift()returns the new length- it does not return the updated array
Correct version:
const arr = [23, 45];
arr.unshift(34);
console.log(arr); // [34, 23, 45]
Mistake 2: Mutating an array when you wanted a new one
Broken code:
const original = [23, 45];
const alias = original;
alias.unshift(34);
console.log(original); // [34, 23, 45]
Why it happens:
aliasandoriginalpoint to the same array
Correct version:
const original = [23, 45];
const updated = [34, ...original];
console.log(original); // [23, 45]
console.log(updated); // [34, 23, 45]
Mistake 3: Using push() instead of unshift()
Broken code:
const arr = [23, 45, 12, 67];
arr.push(34);
console.log(arr); // [23, 45, 12, 67, 34]
Why it happens:
push()adds to the end, not the beginning
Correct version:
arr.unshift(34);
Mistake 4: Trying to beat O(n) with a normal array prepend
Many beginners assume there must be a constant-time trick for normal arrays. In standard JavaScript arrays, prepending generally still requires shifting items, so it is usually O(n).
Mistake 5: Writing unnecessary cleanup code
Code like this is not needed:
delete newArray;
Why:
deleteis not how you normally remove local variables- JavaScript uses garbage collection
- local variables go away when they are no longer referenced
Comparisons
Here is how the main options compare.
| Approach | Mutates original array? | Returns | Typical use |
|---|---|---|---|
unshift(value) | Yes | New length | Simple in-place prepend |
[value, ...array] | No | New array | Immutable updates |
[value].concat(array) | No | New array | Older non-mutating style |
| Manual loop | Usually no, unless assigned back | Depends on code | Rarely needed for this task |
unshift() vs push()
| Method | Adds where? | Mutates? |
|---|---|---|
unshift() | Beginning | Yes |
push() | End | Yes |
unshift() vs spread syntax
const arr = [23, 45];
arr.unshift(34); // arr becomes [34, 23, 45]
const arr = [23, 45];
const updated = [34, ...arr]; // arr unchanged
Choose unshift() when changing the same array is fine.
Choose spread syntax when you want to preserve the original array.
Complexity note
All common prepend approaches for standard arrays are effectively O(n) because existing elements need to move or be copied.
Cheat Sheet
// Mutating prepend
arr.unshift(value);
// Mutating prepend of multiple values
arr.unshift(v1, v2, v3);
// Non-mutating prepend with spread
const updated = [value, ...arr];
// Non-mutating prepend with concat
const updated = [value].concat(arr);
Key rules
unshift()adds elements to the start of an arrayunshift()mutates the arrayunshift()returns the new lengthpush()adds to the end, not the beginning- Prepending to a normal array is usually O(n)
Quick examples
const a = [2, 3];
a.unshift(1);
console.log(a); // [1, 2, 3]
const a = [2, 3];
const b = [1, ...a];
console.log(a); // [2, 3]
console.log(b); // [1, 2, 3]
Edge cases
arr.unshift()with no arguments changes nothingunshift(undefined)addsundefinedas a real element- multiple arguments keep their order:
const arr = [3, 4];
arr.unshift(1, 2);
console.log(arr); // [1, 2, 3, 4]
FAQ
Is there a built-in JavaScript method to add an item to the beginning of an array?
Yes. Use array.unshift(value).
Does unshift() change the original array?
Yes. unshift() mutates the existing array.
What does unshift() return in JavaScript?
It returns the new length of the array, not the array itself.
How do I prepend without modifying the original array?
Use spread syntax or concat():
const updated = [value, ...original];
Is prepending to a JavaScript array O(1)?
Usually no. It is generally O(n) because existing elements need to shift or be copied.
Can I add multiple elements to the beginning at once?
Yes.
arr.unshift(1, 2, 3);
Should I use unshift() in React state updates?
Usually no, because React state should be treated as immutable. Prefer:
setItems([newItem, ...items]);
Is a manual loop ever necessary for prepending?
Usually not. Built-in methods like unshift() or non-mutating patterns are clearer and less error-prone.
Mini Project
Description
Build a small recent-search tracker. Each time a user performs a search, the newest search term should appear at the beginning of the list. This is a practical example of prepending items to an array and limiting the list to a fixed size.
Goal
Create a function that adds a new search term to the beginning of an array and keeps only the 5 most recent searches.
Requirements
- Start with an array of existing search terms.
- Add each new search term to the beginning of the array.
- Keep only the 5 most recent terms.
- Ignore empty search strings.
- Print the updated list after each insert.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.