后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本:
- 最后放进去的元素最先出来
-想象往筒状容器里放盘子:
(1)你放进的最后一个盘子(最新放的)会放在最顶部
(2)当你要取盘子时,只能从顶部开始取
(3)最后放进去的盘子最先被取出 - 与栈(Stack)的关系
-LIFO 是栈结构的核心特性
-JavaScript 的调用栈(Call Stack) 就是典型栈结构
-操作示例:
// 模拟栈操作
const stack = [];
// 入栈 (push)
stack.push("任务1"); // 栈底 ["任务1"]
stack.push("任务2"); // ["任务1", "任务2"]
stack.push("任务3"); // ["任务1", "任务2", "任务3"] ← 栈顶// 出栈 (pop) - 遵循LIFO
console.log(stack.pop()); // "任务3" (最后进的先出)
console.log(stack.pop()); // "任务2"
console.log(stack.pop()); // "任务1"
- 调用栈中的 LIFO 实例
function A() {console.log("进入A");B(); // 调用B函数console.log("离开A");
}function B() {console.log("进入B");C(); // 调用C函数console.log("离开B");
}function C() {console.log("进入C");console.log("离开C");
}A(); // 启动调用
执行顺序(LIFO 体现):
1. A() 入栈 → 栈:[A]
2. B() 入栈 → 栈:[A, B]
3. C() 入栈 → 栈:[A, B, C]
4. C() 执行完出栈 → 栈:[A, B]
5. B() 执行完出栈 → 栈:[A]
6. A() 执行完出栈 → 栈:[]
输出结果:
进入A
进入B
进入C
离开C
离开B
离开A
- LIFO vs FIFO(先进先出)
特性 | LIFO(栈) | FIFO(队列) |
---|---|---|
取出顺序 | 最后进的先出 | 最先进的先出 |
典型场景 | 函数调用栈、撤销操作 | 排队系统、消息队列 |
操作方式 | push() / pop() | push() / shift() |
类比 | 叠盘子(从顶部取) | 排队(先到的人先离开) |
- 为什么调用栈需要 LIFO?
- 保证函数嵌套调用的正确性
- 确保内层函数执行完后能正确返回到外层函数
- 通过栈指针高效管理执行上下文
- 避免内存泄漏(自动清理已执行函数的上下文)
关键理解:在 JavaScript 引擎中,每次函数调用都会创建一个新的栈帧(Stack Frame)压入调用栈顶部,函数执行结束时栈帧会从栈顶弹出。正是 LIFO 特性确保了函数执行的嵌套顺序和上下文完整性。