无限递归一定会栈溢出吗

看一个面试题

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,如此往复就会导致栈溢出。

你可能感兴趣的:(#,JS-深入,面试)