Array.prototype.shift()
Removes the first element from an array and returns it, shifting all remaining elements down.
shift()- Added in JavaScript ES3
Return value
anyThe removed element from the array; undefined if the array is empty.
Errors
Throws a TypeError when called on a frozen array or when the length property is not writable in strict mode.
Changelog
- PHP ES3Introduced on Array.prototype.
shift() removes the element at index 0, returns it, moves every remaining element down one index, and decrements length. It mutates the array and returns undefined when there is nothing to remove.
When to reach for it
Pair it with push() to use an array as a FIFO queue: tasks, messages, breadth-first search frontiers. It is also handy for consuming a header row or a leading flag from a parsed list — const header = rows.shift() leaves rows holding only the data.
What trips people up
Cost. Because every remaining element is reindexed, shift() is O(n), and a loop that shifts until empty is O(n²). Engines optimise small arrays, but on tens of thousands of elements a queue built from push/shift becomes visibly slow. The usual fix is to keep a read cursor into the array and never shift at all, or to use two stacks.
The undefined return is ambiguous in the same way as pop(): a while ((item = q.shift()) !== undefined) loop terminates early if a real undefined is in the queue. Check length instead. For a non-mutating version, arr.slice(1) returns the tail as a new array.
Example
When to use it
- Process a task queue in first-in-first-out order alongside push()
- Strip the header row off a parsed CSV before mapping the data
- Run a breadth-first traversal using an array as the frontier
- Consume the leading command from an argument list
Frequently asked questions
What is the difference between shift() and pop()?
shift() removes the first element and reindexes the rest, while pop() removes the last and does not; shift is O(n) and pop is O(1).
How do I remove the first element without mutating the array?
Use arr.slice(1), which returns a new array containing everything after the first element and leaves the original unchanged.
Why is my push/shift queue slow?
Every shift() moves all remaining elements down one index, so draining n items costs O(n squared); keep a read cursor into the array or use two stacks instead.
More examples
Breadth-first traversal
Taking from the front while adding to the back visits every node level by level. The same loop with pop() instead of shift() would produce depth-first order.
const tree = { v: 1, kids: [{ v: 2, kids: [] }, { v: 3, kids: [{ v: 4, kids: [] }] }] };
const frontier = [tree];
const order = [];
while (frontier.length) {
const node = frontier.shift();
order.push(node.v);
frontier.push(...node.kids);
}
console.log(order.join(" -> ")); // 1 -> 2 -> 3 -> 4Separating a header row
shift() pulls the header out and leaves rows containing only data, so the map afterwards does not need an index offset. The final line zips each row against the header names.
const rows = [
["id", "name"],
["1", "ada"],
["2", "grace"],
];
const header = rows.shift();
console.log(header); // ['id','name']
console.log(rows.length); // 2 — only data remains
const objects = rows.map((r) => Object.fromEntries(r.map((v, i) => [header[i], v])));
console.log(objects);Avoiding the quadratic drain
Advancing an index reads the same sequence in the same order without moving any elements. On a large queue this is linear overall, where shifting until empty would be quadratic.
const items = Array.from({ length: 5 }, (_, i) => i);
// Cursor approach: no reindexing at all.
let cursor = 0;
while (cursor < items.length) {
console.log("item", items[cursor]);
cursor++;
}
console.log(items.length); // 5 — array untouched
Discussion