Array.prototype.shift()

Removes the first element from an array and returns it, shifting all remaining elements down.

Signature
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

Try it yourself
Loading editor…
Press Run to execute the code.

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.

Example · javascript
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 -> 4

Separating 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.

Example · javascript
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.

Example · javascript
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

  • Be the first to comment on this lesson.