Fundamentals 12 min read

Understanding Stacks: Concepts, Common Use Cases, and JavaScript Implementations

This article explains the stack data structure, its LIFO characteristics, typical applications such as bracket matching, expression evaluation, next‑greater‑element problems, browser navigation, and JavaScript execution contexts, and provides clear JavaScript code examples for each scenario.

New Oriental Technology
New Oriental Technology
New Oriental Technology
Understanding Stacks: Concepts, Common Use Cases, and JavaScript Implementations

A stack is a fundamental data structure that follows a Last‑In‑First‑Out (LIFO) principle, allowing insertion and removal of elements only at one end.

Typical characteristics: only one end supports push and pop operations, and the order is LIFO.

Common scenarios where a stack is useful include:

Bracket matching

Expression evaluation

Next greater element

Browser forward/backward navigation

JavaScript execution context stack

Bracket Matching

To verify whether a string containing parentheses, brackets, and braces is valid, scan the string from left to right, pushing left symbols onto a stack and popping when a matching right symbol is found. The string is valid if the stack is empty at the end.

function validString(string) {
  const resultStack = [];
  const markMap = new Map([
    ["(", ")"],
    ["[", "]"],
    ["{", "}"]
  ]);
  const top = arr => arr[arr.length - 1];

  for (let i = 0; i < string.split("").length; i++) {
    const str = string[i];
    const isLeft = markMap.get(str);
    if (isLeft) {
      resultStack.push(str);
      continue;
    }
    const isRelative = str === markMap.get(top(resultStack));
    if (!isRelative) {
      return false;
    }
    resultStack.pop();
  }
  return !resultStack.length;
}
console.log(validString("[[({}{})]]({})")); // true

Expression Evaluation

Using two stacks—one for operands and one for operators—allows evaluation of arithmetic expressions respecting operator precedence.

const priorityMap = { "+": 0, "-": 0, "*": 1, "/": 1 };
const computeMap = {
  "+": (a, b) => a + b,
  "-": (a, b) => a - b,
  "*": (a, b) => a * b,
  "/": (a, b) => a / b,
};
const top = arr => arr[arr.length - 1];
const top2 = arr => arr[arr.length - 2];
const isEmpty = arr => !arr.length;
const compute = (numberStack, markStack) => {
  const computeFn = computeMap[markStack[markStack.length - 1]];
  const result = computeFn(top2(numberStack), top(numberStack));
  markStack.pop();
  numberStack.pop();
  numberStack.pop();
  numberStack.push(result);
};
function computeExpression(expressionString) {
  const markStack = [];
  const numberStack = [];
  expressionString.split("").forEach(str => {
    const isMark = priorityMap.hasOwnProperty(str);
    if (!isMark) {
      numberStack.push(str - 0);
      return;
    }
    while (!isEmpty(markStack) && priorityMap[str] <= priorityMap[top(markStack)]) {
      compute(numberStack, markStack);
    }
    markStack.push(str);
  });
  while (markStack.length) {
    compute(numberStack, markStack);
  }
  const result = top(numberStack);
  numberStack.pop();
  return result;
}
console.log(computeExpression("1+2*5*1+4/2+5")); // 18

Next Greater Element

Given an array, the task is to produce an array where each position holds the next greater element to its right, or -1 if none exists. A monotonic decreasing stack yields an O(n) solution.

const top = arr => arr[arr.length - 1];
const isEmpty = arr => !arr.length;
var nextGreaterElement = function(numbers) {
  const stack = [];
  let ans = [];
  for (let i = numbers.length - 1; i >= 0; i--) {
    const cur = numbers[i];
    while (!isEmpty(stack) && cur >= top(stack)) {
      stack.pop();
    }
    ans[i] = isEmpty(stack) ? -1 : top(stack);
    stack.push(cur);
  }
  return ans;
};

Daily Temperatures (Next Greater in Time)

For each day’s temperature, compute how many days must pass until a warmer temperature occurs; use a stack that stores indices.

var dailyTemperatures = function(numbers) {
  const stack = [];
  let ans = [];
  for (let i = numbers.length - 1; i >= 0; i--) {
    const cur = numbers[i];
    while (!isEmpty(stack) && cur >= numbers[top(stack)]) {
      stack.pop();
    }
    ans[i] = isEmpty(stack) ? 0 : top(stack) - i;
    stack.push(i);
  }
  return ans;
};

Circular Next Greater Element

When the array is considered circular, iterate twice over the array using modulo arithmetic to simulate the wrap‑around.

var nextGreaterElement = function(numbers) {
  const stack = [];
  let ans = [];
  for (let i = numbers.length * 2 - 1; i >= 0; i--) {
    const cur = numbers[i % numbers.length];
    while (!isEmpty(stack) && cur >= top(stack)) {
      stack.pop();
    }
    if (i < numbers.length) {
      ans[i] = isEmpty(stack) ? -1 : top(stack);
    }
    stack.push(cur);
  }
  return ans;
};

Browser Forward/Backward Navigation

Two stacks (back‑stack and forward‑stack) model the browser’s history: navigating to a new page pushes it onto the back‑stack; back moves the top page to the forward‑stack; forward moves it back; visiting a new page clears the forward‑stack.

JavaScript Execution Context Stack

JavaScript’s single‑threaded engine uses an execution context stack: the global context is pushed first, each function call creates a new context pushed on top, and contexts are popped when functions return.

var color = 'blue';
function changeColor() {
  var anotherColor = 'red';
  function swapColors() {
    var tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;
  }
  swapColors();
}
changeColor();

These examples illustrate how the stack abstraction underlies many core programming tasks and system behaviors.

algorithmJavaScriptStackData StructuresMonotonic Stacknext greater element
New Oriental Technology
Written by

New Oriental Technology

Practical internet development experience, tech sharing, knowledge consolidation, and forward-thinking insights.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.