看一个面试题
function foo(){
setTimeout(foo, 0)
}
关于栈溢出我们都有一个感觉就是无限递归就会导致栈溢出,为什么呐?
很简单,因为栈它是一块内存空间,每一次的函数调用都相当于往这个函数里面添加了一个执行上下文,那如果说这一次函数调用还没结束又调用了自身,那又会加一个,直到把整个栈加满,空间不够了,就叫做栈溢出。
所以说,如果到了代码层面,你这样写:
function foo(){
foo()
}
foo()
这个就是一个典型的无限递归的场景,自身的函数还没有执行完就开始调用自身,你执行一下最终会导致栈溢出,会报栈溢出的错。
但是如果是面试题的那种写法呐?这种写法会不会导致栈溢出呐?
function foo(){
setTime out(foo, 0)
}
这里你执行就会发现,无论等多久都不会发生栈溢出的报错。
那为什么呐?这里不是也是无限递归吗?这里为什么没有发生栈溢出的报错?
一开始执行foo的时候,往栈里面添加了一个上下文,在这个执行期间,它会开启一个计时器,计时器到达之后会再一次执行foo,但是定时器是异步的,也就是说这个函数本身不会等待这个计时器结束才去结束,foo该运行结束就会运行结束,运行结束之后就会出栈,然后才是计时器到达,如此往复,所以不会发生栈溢出。
虽然是无限递归下去,cpu忙的要死,但不会导致栈溢出。
这个题还有很多的变种,比方说,这一块写成下面这个样子,需要想一想这样子做会不会导致栈溢出
function foo(){
setTimeout( foo(), 0)
}
foo()
你执行发现,这样一些又会导致栈溢出,因为这一次调用foo函数是在计时器之前你要作为参数传进去,所以说你调用这个函数把他的返回结果作为参数传到这个计时器,在计时器之前又调用了这个函数,就会出现本次foo的函数没有运行结束就会运行下一个foo,如此往复就会导致栈溢出。