Stacks
A stack only lets you touch the most recently added item: last in, first out.
Loading visual…
Definition
A stack is a collection with a single point of entry and exit, the top. Adding an item is called push, and it always places the new item on top; removing an item is called pop, and it always removes whatever is currently on top. Because both operations only ever touch the top, they run in O(1) time regardless of how many items are underneath, and the order items come back out is the reverse of the order they went in: last in, first out (LIFO). This last-in-first-out order is exactly what JavaScript's own call stack uses to track which function is running: calling a function pushes a new frame, and returning from it pops that frame back off, resuming whichever frame is now on top. The same shape shows up anywhere "undo the most recent thing" or "finish the innermost thing first" is the natural rule, which is why stacks are also the standard tool for matching nested brackets and for backtracking algorithms.
Examples
const stack = [];
stack.push(10);
stack.push(20);
stack.push(30);
stack.pop(); // 30
stack[stack.length - 1]; // 20 (peek)push adds to the top of the array, pop removes and returns the top, and the last value pushed (30) is the first one to come back off.
function isBalanced(str) {
const stack = [];
const pairs = { ")": "(", "]": "[", "}": "{" };
for (const ch of str) {
if ("([{".includes(ch)) stack.push(ch);
else if (ch in pairs) {
if (stack.pop() !== pairs[ch]) return false;
}
}
return stack.length === 0;
}
isBalanced("([{}])"); // true
isBalanced("([)]"); // falseEvery opening bracket is pushed, and every closing bracket must match whatever is currently on top; if it does not, or if brackets are left over at the end, the string is not balanced.
class UndoStack {
#actions = [];
do(action) { this.#actions.push(action); }
undo() { return this.#actions.pop(); }
}
const history = new UndoStack();
history.do("bold");
history.do("italic");
history.undo(); // "italic"The most recently applied action is always the first one undone, which is exactly LIFO order.
Common mistakes
- Calling pop() on an empty stack and getting undefined back instead of an error, letting the bug propagate silently.
- Confusing a stack's last-in-first-out order with a queue's first-in-first-out order when picking a structure for a problem.
- Using shift/unshift on an array to implement a stack; those are O(n) operations, unlike the O(1) push/pop at the end.
Key takeaways
- Stacks only expose the top element: push adds, pop removes, and both run in O(1).
- LIFO ordering fits nested or reversible operations, like undo history and bracket matching, naturally.
- Pushing and popping at the end of a JavaScript array is the efficient way to implement a stack.
You push 1, then 2, then 3 onto a stack. What do two consecutive pop() calls return, in order?
Where you see this
- The JavaScript call stack itself, tracking which function is currently running.
- Undo and redo history in a text or design editor.
- Matching brackets, tags, or parentheses when parsing code or markup.
- Backtracking algorithms like maze solving or depth-first search, using an explicit stack instead of recursion.