内存中的堆栈和数据机构中的堆栈不是一个概念,内存中的堆栈是真实存在的物理区,数据结构中的堆栈是抽象数据存储结构。
我们可以利用栈这个数据结构,理解JS的运行机制之:JS调用栈
1. 全局执行上下文:先创建全局对象,再将this指向这个全局对象。
2. 函数执行上下文:每次调用函数的时候,会为这个函数创建一个新的执行上下文。
3. Eval函数执行上下文:`eval()`
const one = () => {
two();
console.log('我是one');
}
const two = () => {
console.log('我是two');
}
one();
- 每当发生函数调用的时候,JS引擎都会为该函数创建一个新的执行上下文并push到当前执行栈的栈顶。
- 当调用 one 函数的时候,JS引擎都会为该函数创建一个新的执行上下文并推到当前执行栈的栈顶。
- 当调用 two 函数的时候,JS引擎都会为该函数创建一个新的执行上下文并推到当前执行栈的栈顶。
- 当two函数调用完毕后,他的执行上下文就会从当前执行栈中弹出,上下文的控制权移到当前执行栈中的下一个执行上下文:one 函数
我们可以利用栈这个数据结构,理解JS的运行机制之:递归的原理
const factor = (n)=>{
// 递归要有出口,否则就是死循环
if(n === 1){
return 1;
}
return n * factor(n - 1);
}
console.log(factor(3)); // 6
console.log(factor(10)); // 3628800
// 尾调用
function a(x){}
function b(x){
return a(x);
}
// 尾调用自身就是尾递归
const factor = (n, total)=>{
if(n === 1){
return total;
}
return factor(n - 1, n * total);
}
// 递归
const Fibonacci = (n) => {
if(n<=1){
return 1;
}
return Fibonacci(n-1)+Fibonacci(n-2);
}
/*
会存在一个重复计算问题
n = 5, Fibonacci(4)+Fibonacci(3)
n = 4, Fibonacci(3)+Fibonacci(2)
...
*/
console.log(Fibonacci(50)); // 运行直接卡死
// 尾递归
// 把前面2位数,当作参数传进来
const Fibonacci = (n, ac1=1, ac2=1) => {
if(n<=1){
return ac2;
}
return Fibonacci(n-1, ac2, ac1+ac2);
}
console.log(Fibonacci(50)); // 运行就很流畅
栈的应用有:十进制转二进制
JavaScript
实现一个栈结构class Stack{
constructor() {
this.items = [];
}
// 入栈
push(ele){
this.items.push(ele);
}
// 出栈
pop() {
return this.items.pop();
}
// 获取栈顶元素
peek(){
return this.items[this.items.length - 1];
}
// 查看栈是否为空
isEmpty(){
return this.items.length === 0;
}
// 查看栈中元素个数
size(){
return this.items.length;
}
// 清空栈
clear(){
this.items = []
}
}
const stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
console.log(stack);
// 十进制转二进制
const binary = (number) =>{
let stack = new Stack();
let remainder = 0;
let top = '';
while(number > 0){
// 除于2取余数
remainder = number % 2;
stack.push(remainder);
// 向下取整
number = Math.floor(number / 2);
}
// 不为空的时候
while(!stack.isEmpty()){
// 栈顶元素
top += stack.pop();
}
return top;
}
console.log("2 = ", binary(2))