求解释js递归

function foo(i) {
  if (i < 0)
  return;
  console.log('begin:' + i);
  foo(i - 1);
  console.log('end:' + i);
}
foo(3);

// begin:3
// begin:2
// begin:1
// begin:0
// end:0
// end:1
// end:2
// end:3

求帮忙解释这段代码的流程,本人太菜所以希望大神详细点。

阅读 6k
评论 2015-11-02 提问
    7 个回答
    kikong
    • 18.3k
    function foo(i) {
      if (i < 0)
      return;
      console.log('begin:' + i);
      foo(i - 1);
      console.log('end:' + i);
    }
    foo(3);

    foo函数首先被定义
    foo(3)[foo3,i=3]开始执行函数
    在函数内部i=3 执行 console.log; begin:3
    执行到foo(2)[foo2,i=3],在此处假设存在一个检查点checkpoint CP2,
    再次进入foo函数,i=2 执行console.log;begin:2
    执行到foo(1)[foo1,i=2],在此处假设存在一个检查点checkpoint CP1,
    再次进入foo函数,i=1 执行console.log;begin:1
    执行到foo(0)[foo0,i=1],在此处假设存在一个检查点checkpoint CP0,
    再次进入foo函数,i=0 执行console.log;begin:0
    执行到foo(-1)[foo-1,i=0],在此处假设存在一个检查点checkpoint CP-1,
    再次进入foo函数,i=-1,i<0;foo函数return;此时返回的CP-1,
    [foo-1]执行结束,从CP-1往下执行,此时i=0,执行console.log;end:0
    [foo0]执行结束,从CP0往下执行,i=1,,执行console.log;end:1
    [foo1]执行结束,从CP1往下执行,i=2,,执行console.log;end:2
    [foo2]执行结束,从CP2往下执行,i=3,,执行console.log;end:3,[foo3]也执行结束

    [foo3[foo2[foo1[foo0[foo-1]]]]]

    评论 赞赏 2015-11-03
      admos
      • 590

      这是函数栈,如果不清楚栈,先去了解栈。然后想象一下,每次去把执行的函数压栈,执行完毕再出栈。即可。

      评论 赞赏 2015-11-02

        看看下面的执行过程应该就能明白了。

        执行流程示意

        评论 赞赏 2015-11-03
          function foo(i) {
              if (i < 0)
                  return;
              console.log('begin:' + i);
              foo(i - 1);
              console.log('end:' + i);
          }

          //你把代码 拓展开成这样。。。

          foo(2) {
              console.log('begin:' + 2);
              foo(1){
                  console.log('begin:' + 1);
                  foo(0){
                      console.log('begin:' + 0);
                      foo(-1){
                          return
                      }
                      console.log('end:' + 0);
                  }
                  console.log('end:' + 1);
              }
              console.log('end:' + 2);
          }
          foo(3);
          评论 赞赏 2015-11-03

            你直接跟踪一下函数的运行,比如当i=3是,f(3)--3-->f(2)--2-->f(1)--1-->f(0)--0-->f(-1),当i=-1,return跳出函数.执行console.log返回0,1,2,3

            评论 赞赏 2015-11-03

              你可以理解当函数执行到foo(i-1)时,程序会将foo(i-1)执行完成后,再执行console.log("end:"+i)

              评论 赞赏 2015-11-03
                一个菜鸟的奋斗史
                • 2
                • 新人请关照

                第一次进入函数foo(3),此时的参数为3,假设为foo1()被推入执行栈
                首先 i不小于0,输出begin:3
                进入foo(i - 1),参数为3-1 = 2,假设为foo2()被推入执行栈
                i不小于0,输出begin:2
                进入foo(i - 1),参数为2-1 = 1,假设为foo3()被推入执行栈
                i不小于0,输出begin:1
                进入foo(i - 1),参数为1-1 = 0,假设为foo4()被推入执行栈
                i不小于0,输出begin:0
                进入foo(i - 1),参数为0-1 = -1,假设为foo5()被推入执行栈
                i小于0 return,执行栈弹出当前的函数foo5(),进入到上一个函数foo4(),继续执行未完成的代码
                输出end:0
                执行栈弹出当前的函数foo4(),进入到上一个函数foo3(),继续执行未完成的代码
                输出end:1
                执行栈弹出当前的函数foo3(),进入到上一个函数foo2(),继续执行未完成的代码
                输出end:2
                执行栈弹出当前的函数foo2(),进入到上一个函数foo1(),继续执行未完成的代码
                输出end:3
                执行栈弹出当前的函数foo1(),到此执行栈全部执行完毕

                评论 赞赏 2019-01-15
                  撰写回答

                  登录后参与交流、获取后续更新提醒