开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
什么是调用栈?
调用栈是JavaScript维护出来的一种栈结构,作用就是用来分类管理代码的执行上下文的。 存储顺序是按照代码中函数的调用顺序。 通常把这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈。
理解调用栈
现在我们看下面这串代码:
var a = 2
function p2(b,c){
return b+c
}
function p1(b,c){
var d = 10
result = p2(b,c)
return a+result+d //2+9+10
}
console.log(p1(3,6));//21
以上代码中调用栈的执行过程是怎么样的呢?
- 首先创建全局执行上下文
我们可以看见已经把全局执行上下文压入栈中,全局作用域下的变量和函数已经声明好。接下来就是代码的执行。
- 首先是将全局执行上下文中的a赋值为2
- 而后是p1的调用,创建p1的执行上下文并压入栈中
- 创建好p1的执行上下文后执行代码。
- 形参和实参统一,变量赋值d=10
- result = p2(3,6)
- p2的调用触发p2的上下文进入调用栈
- p2的执行完毕返回值给p2的调用result,并且p2执行上下文出站。
- p1的执行完毕接着就是p1执行上下文出站。
- 执行console.log(p1(3,6))
- 接着就是全局执行上下文出栈。意味着代码的执行完毕
以上就是这段代码的调用栈执行过程。
什么是栈溢出?
现在我们知道了调用栈是来管理执行上下文的数据结构的,遵循后进先出准则。但是调用栈是有大小限制的,当入栈的执行上下文超过一定的数目,JavaScript引擎就会报错。我们我这种报错叫栈溢出。
我们可以看看下面这串代码:
function add(a){
return add(a+1)
}
console.log(add(1));
在调用add函数的时候,又调用了自己。这样的程序是不是一个没有停止条件的递归呢?
- 不管在node环境还是在浏览器环境下,都会出现栈溢出的报错(超过了最大栈调用大小)
node环境
浏览器环境
所以在日常coding中,慎用递归是非常影响性能的,一不小心就会出现堆栈溢出的情况