jsguides

Array.prototype.shift()

shift()

shift() removes and returns the first element of an array. It modifies the array in place, reducing its length by 1 and shifting all other elements to a lower index.

Syntax

arr.shift()

Since shift() mutates the array in place, the original array permanently loses its first element. The removed value is returned to the caller, which is useful when consuming items from a queue one at a time. The method takes no arguments and returns undefined for empty arrays instead of throwing, so check the return value when emptiness is ambiguous.

Examples

Basic usage

const fruits = ["apple", "banana", "cherry"];
const first = fruits.shift();

console.log(first);
// "apple"

console.log(fruits);
// ["banana", "cherry"]

The first call to shift() returns the element at index 0 and shortens the array by one. When the array is already empty, the behavior changes: shift() returns undefined and leaves the array unchanged rather than throwing an error.

Working with empty arrays

const empty = [];
const result = empty.shift();

console.log(result);   // undefined
console.log(empty);    // []

Common Patterns

Beyond simple element removal, shift() supports several recurring JavaScript patterns. The examples below cover queue processing, data structure implementation, and legacy argument handling. Each illustrates a situation where removing from the front is the correct choice.

Using shift() in a loop

Processing items from the front is common in task runners and job queues. When the array represents pending work, shifting off the first item mirrors the natural order of a queue:

function processQueue(queue) {
  while (queue.length > 0) {
    const item = queue.shift();
    console.log("Processing:", item);
  }
}

const tasks = ["task1", "task2", "task3"];
processQueue(tasks);
// Processing: task1
// Processing: task2
// Processing: task3

The loop approach works for one-off processing, but wrapping the pattern in a class gives you a reusable FIFO structure with clean enqueue and dequeue semantics. This is the foundation of many task runners, event loops, and job schedulers.

Implementing a queue

shift() is commonly used to implement a queue data structure (FIFO - first in, first out):

class Queue {
  constructor() {
    this.items = [];
  }
  
  enqueue(item) {
    this.items.push(item);
  }
  
  dequeue() {
    return this.items.shift();
  }
  
  peek() {
    return this.items[0];
  }
}

const queue = new Queue();
queue.enqueue("first");
queue.enqueue("second");
console.log(queue.dequeue()); // "first"
console.log(queue.dequeue()); // "second"

Modern JavaScript uses rest parameters (...args) for variable-length argument lists, so this pattern is mostly historical. If you encounter code calling Array.prototype.slice.call(arguments), it does what ...args handles natively in current language versions.

Converting arguments to array

Before rest parameters existed, arguments were converted to array using Arrayslice.call() or shift():

function example() {
  const args = Arrayslice.call(arguments);
  console.log(args);
}

example(1, 2, 3);
// [1, 2, 3]

Behavior Notes

  • shift() returns undefined on empty arrays
  • This method modifies the original array (mutating method)
  • All remaining elements shift down by one index

Performance

shift() is O(n) — every element after the removed first element must be re-indexed (shifted down by one). For large arrays where you frequently remove from the front, this cost is significant. A common optimization for FIFO queues is to use a pointer or index instead of actually removing elements, or to use a data structure designed for deque operations.

shift() vs pop()

shift() removes from the beginning; pop() removes from the end. pop() is O(1) because no re-indexing is needed — the last element is simply removed. When building queues, combining push() (add to end) with shift() (remove from front) is semantically clear but O(n) per dequeue. For high-throughput queues, consider reversing the convention: push at the front with unshift() and pop from the end with pop().

Return value

shift() returns the removed element — the value that was at index 0. On an empty array it returns undefined without throwing. Always check the return value if you need to distinguish between “the first element was undefined” and “the array was empty”:

const arr = [undefined, 1, 2];
arr.shift(); // undefined — but array had 3 elements, now has 2
const empty = [];
empty.shift(); // undefined — array was empty

When shift() makes sense

shift() makes sense when the first item is meant to be consumed and removed, such as in queue processing or turn-based workflows. It mirrors the idea of taking the next item off the front of a line, which is easy to understand in both code and business logic.

The tradeoff is that removing the first element forces the rest of the array to move down one index. That is fine for small queues and short lists, but if you need to pop from the front at scale, a different data structure is usually a better fit.

See Also