news 2026/6/11 23:41:23

食堂阿姨看了都要点赞:这个“栈“究竟是个什么鬼?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
食堂阿姨看了都要点赞:这个“栈“究竟是个什么鬼?

先别急,我们来看看以下场景

想象一下,你在一个特别小的食堂里打饭。

食堂阿姨贼凶,只从一头上菜。

你端着餐盘走过去,阿姨依次给你放了:

米饭 → 红烧肉 → 青菜 → 煎蛋

好家伙,堆了四层。

但你端到座位上准备吃的时候,你第一口吃的是什么?

煎蛋。

因为它就在最上面,最好拿。

而最后一口吃的是米饭,因为它在最底下,被压得最深。

恭喜你,刚才你无意识地用了一次"栈"。


到底什么是栈?

栈(Stack),就是一种只能从一端操作数据的数据结构。

你只能:

  • 往里放东西(叫"入栈",push)

  • 往外拿东西(叫"出栈",pop)

而且有个铁律:后来居上,先走一步。

专业点说叫LIFO:Last In First Out。

说人话:最后进去的,最先出来。

就像叠盘子、子弹上膛、IDE的撤销操作——都是栈的经典应用。


栈的几个重要概念

栈顶(Top):就是那个最上面、最容易被拿走的元素(煎蛋就是栈顶)。
栈底(Bottom):就是那个被压在最底下、最难被拿到的元素(米饭就是栈底)。
入栈(Push):把新元素放到最上面
Push 五花肉 ← 五花肉(新来的,站在最上面) ← 煎蛋 ← 青菜 ← 红烧肉 ← 米饭(最老的,被压在最底下)
出栈(Pop):把最上面的元素拿走
Pop 一下 ← 青菜 ← 煎蛋被拿走了(走了走了) ← 红烧肉 ← 米饭


前端最熟悉的栈:函数调用栈

每天写代码,其实无时无刻不在跟栈打交道。**

当 JavaScript 执行一段代码时,它用调用栈(Call Stack)来记住现在执行到哪了。

看这个例子:

这段代码执行时,调用栈是这么变化的:

第1步:调用 daily → Stack: [daily] 第2步:调用 lunch → Stack: [lunch, daily] 第3步:调用 eat → Stack: [eat, lunch, daily] 第4步:eat 执行完出栈 → Stack: [lunch, daily] 第5步:lunch 执行完 → Stack: [daily] 第6步:daily 执行完 → Stack: []

看到了吗?eat 是最后进去的,但它最先出来。

这,就是栈。


栈有什么特点?必须记住这4条

1. 后进先出(LIFO)

这是栈的灵魂。不接受反驳,没有例外。

2. 只有栈顶能操作

栈底的东西想出来?等上面所有人都走了再说。

3. 没有随机访问

普通数组你可以随便拿第5个元素,但栈不行。

你想拿到栈底的米饭?必须先把煎蛋、青菜、红烧肉全部 Pop 出去。

4. 操作只有 O(1)

入栈和出栈都是常量时间,不需要遍历,不需要找来找去,就是快。


前端场景中常用的栈

案例一:JS 引擎的调用栈

上面刚讲过。每次你调一个函数,就入栈;函数执行完,就出栈。

为什么你写递归写多了会报"Maximum call stack size exceeded"?

因为栈太深了,内存装不下了。

// 这种无限递归,调用栈会爆炸 functionrecursion() { recursion(); } recursion(); // Uncaught RangeError: Maximum call stack size exceeded

案例二:浏览器历史记录(前进/后退)

浏览器的前进和后退功能,背后就是一个栈。

案例三:撤销操作(Ctrl+Z)

你在 VSCode 里疯狂 Ctrl+Z,为什么能把你的操作一步步撤销回来?

因为编辑器内部维护了一个操作栈

你做了:打字 → 删掉 → 粘贴 → 撤销 ↓ ↓ ↓ ↓ Stack: [打字] [打字,删掉] [打字,删掉,粘贴] [打字,删掉]

每次撤销就是一次 Pop,栈顶的操作被取消掉。

案例四:括号匹配

写 JS 的时候有没有想过,IDE 怎么知道你写的{[(什么)]}有没有少一个括号?

用栈来判断:

functionisValid(str) { conststack= []; constmap= { ')': '(', ']': '[', '}': '{' }; for (constcharofstr) { if ('([{'.includes(char)) { // 开括号:入栈 stack.push(char); } else { // 闭括号:检查栈顶是不是对应的开括号 if (stack.pop() !==map[char]) { returnfalse; // 不匹配,凉了 } } } // 栈空 = 全部匹配成功 returnstack.length===0; } isValid('{ [ ( ) ] }'); // true isValid('{ [ ( ] ) }'); // false ← 括号乱套了

案例五:Vue/React 中的组件渲染栈(简化理解)

React 的协调(Reconciliation)过程,虽然内部用的是链表,但从概念上也可以用栈来理解——子组件的渲染和卸载,本质上遵循后进先出的顺序。


用 JavaScript 五行代码实现一个栈

别被"数据结构"四个字吓到,栈的实现简单到离谱:

classStack { constructor() { this.items= []; // 用数组存,数据不会丢 } push(item) { this.items.push(item); // 入栈 } pop() { returnthis.items.pop(); // 出栈 } peek() { returnthis.items[this.items.length-1]; // 看一眼栈顶是谁 } isEmpty() { returnthis.items.length===0; // 空不空? } } // 用起来 conststack=newStack(); stack.push('米饭'); stack.push('红烧肉'); stack.push('青菜'); stack.push('煎蛋'); stack.pop(); // '煎蛋' ← 最后一个进来的,第一个出来 stack.pop(); // '青菜'

栈这个数据结构,看起来简单,但到处都在用

你写的每个函数调用、每次撤销操作、每个括号校验、浏览器的前进后退——背后都是栈在默默工作。

搞懂了栈,你就算是真正踏进了"程序员的思维世界"。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 18:51:13

abap2xlsx架构解析:ABAP Excel生成库深度指南与最佳实践

abap2xlsx架构解析:ABAP Excel生成库深度指南与最佳实践 【免费下载链接】abap2xlsx Generate your professional Excel spreadsheet from ABAP 项目地址: https://gitcode.com/gh_mirrors/ab/abap2xlsx abap2xlsx是SAP ABAP生态系统中专业级Excel生成库&…

作者头像 李华
网站建设 2026/6/11 1:16:09

数据清洗与结构化:采集完成后,如何让AI提取有效字段?

“网页采了几万条,全是HTML标签和乱码,根本没法用……”“价格字段里混着‘’、‘元’、‘USD’,格式乱七八糟……”“更崩溃的是,同一个产品在不同平台上的字段名完全不一样,人工对齐要疯掉……”如果你做过数据采集&…

作者头像 李华
网站建设 2026/6/10 20:29:40

计算机毕业设计之基于分布式爬虫的外卖甜品数据分析

随着互联网和移动应用的普及,外卖服务已成为人们日常生活中不可或缺的一部分。其中,甜品作为外卖服务的一个重要分类,其市场需求和消费趋势日益受到关注。为了深入了解外卖甜品的市场状况、用户偏好以及消费趋势,分布式爬虫技术被…

作者头像 李华
网站建设 2026/6/11 12:49:26

Trelby剧本写作工具:完全免费的专业剧本创作软件终极指南

Trelby剧本写作工具:完全免费的专业剧本创作软件终极指南 【免费下载链接】trelby The free, multiplatform, feature-rich screenwriting program! 项目地址: https://gitcode.com/gh_mirrors/tr/trelby 你是否梦想成为一名编剧,却被复杂的剧本格…

作者头像 李华