用栈模拟队列:算法题背后的原型链课

11 阅读2分钟

一、一个问题,两个维度

"用两个栈模拟队列"是经典面试题。但它的价值不止于算法——当代码写出来的时候,JavaScript 的原型机制已经隐含在其中。

这道题的独特之处在于:算法的实现过程同时也是理解语言特性的最佳入口。


二、两个栈模拟队列的核心思路

栈是 FILO,队列是 FIFO,方向正好相反。但两个栈配合就能解决:一个专门接收新元素(输入栈),另一个专门处理出队(输出栈)。

关键操作是"倒数据"——当输出栈为空时,把输入栈的所有元素依次弹出并压入输出栈。由于栈的后进先出特性,倒一次之后,最早进入输入栈的元素就到了输出栈的栈顶。

const MyQueue = function () {
    this.stack1 = []; // 输入栈
    this.stack2 = []; // 输出栈
};

MyQueue.prototype.push = function (x) {
    this.stack1.push(x);
};

MyQueue.prototype.pop = function () {
    if (this.stack2.length === 0) {
        while (this.stack1.length > 0) {
            this.stack2.push(this.stack1.pop());
        }
    }
    return this.stack2.pop();
};

MyQueue.prototype.peek = function () {
    if (this.stack2.length === 0) {
        while (this.stack1.length > 0) {
            this.stack2.push(this.stack1.pop());
        }
    }
    return this.stack2[this.stack2.length - 1];
};

MyQueue.prototype.empty = function () {
    return this.stack1.length === 0 && this.stack2.length === 0;
};

push 永远是 O(1),pop 和 peek 均摊 O(1)——每个元素最多被倒两次。


三、prototype 在这段代码里做了什么

上面用 function + prototype 而非 class 来写。这不是怀旧,而是故意暴露 JavaScript 面向对象的底层机制。

MyQueue.prototype 是一个对象,存放所有实例共享的方法。通过 new MyQueue() 创建的每个实例,内部通过 __proto__ 链接到 MyQueue.prototype,从而访问这些方法。

这背后是一个三层三角关系:

  • 构造函数 MyQueueprototype 属性,指向原型对象
  • 原型对象有 constructor 属性,指回构造函数
  • 实例有 __proto__ 属性,指向原型对象

ES6 的 class 只是这个三层关系的语法糖——typeof MyQueue 不管用哪种写法都是 "function"


四、new 操作符的四步流程

new MyQueue() 的执行过程不是魔法,是四步操作:

  1. 创建一个空对象 {}
  2. 将这个对象的 __proto__ 指向构造函数的 prototype
  3. 执行构造函数,this 指向新对象,添加属性
  4. 返回这个对象(除非构造函数显式返回了一个对象)
function myNew(constructor, ...args) {
    const obj = {};
    Object.setPrototypeOf(obj, constructor.prototype);
    const result = constructor.apply(obj, args);
    return result instanceof Object ? result : obj;
}

理解这四步之后,const queue = new MyQueue() 不再是一个黑盒。


五、总结

一道算法题加一个语言特性,二者的交汇点不是巧合:

  1. 用栈模拟队列考察的是数据结构组合思维
  2. prototype 机制是 JavaScript 面向对象的基石
  3. new 操作符 = 创建对象 → 绑定原型 → 初始化 → 返回

当你能从算法实现中看到语言底层的运转时,这两方面的知识就不再是孤立的两本书,而是同一块知识地图的不同区域。