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

一、一个问题,两个维度

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

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


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

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

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

javascript 复制代码
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. 返回这个对象(除非构造函数显式返回了一个对象)
javascript 复制代码
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 操作符 = 创建对象 → 绑定原型 → 初始化 → 返回

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

相关推荐
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄1 天前
JavaScript 隐式全局变量解析
javascript
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端
paopaokaka_luck1 天前
智慧社区综合服务小程序(人脸识别、AI问答、Echarts图形化分析)
前端·javascript·spring boot·spring·数据分析·echarts
Hilaku1 天前
为什么死磕 1px 的团队,用户体验反而更差?
前端·javascript·程序员
陈拉斯1 天前
给公司年会写了个大屏抽奖系统:动画在前端跑,凭什么说结果没被改?
javascript
yzy851 天前
Vue中下载或打开文件的JavaScript方法
前端·javascript·vue
用户298698530141 天前
在 React 中用 JavaScript 将 Word 转换为文本
前端·javascript·react.js
李少兄1 天前
深入解析 JavaScript 中的 `document` 对象
javascript