• 一个JavaScript递归引出的问题


    递归引出问题

     最近在看一本JS方面的书,名字叫《JavaScript语言精粹(修订版)》。在看到递归这一节的时候,有一段代码让我想了大概几分钟才想明白是怎么回事,代码如下:

            var haoni = function(disc, src, aux, dst){
                if(disc > 0){
                    haoni(disc - 1, src, dst, aux);
    
                    document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst + '<br/>');
    
                    haoni(disc -1, aux, src, dst);
                }
            };
    
            haoni(3, 'Src', 'Aux', 'Dst');
    View Code

    这是一个有关“汉诺塔”的js实现代码。我主要是看过输出的结果有点不明白。输出如下:

    Move disc 1 from Src to Dst
    Move disc 2 from Src to Aux
    Move disc 1 from Dst to Aux
    Move disc 3 from Src to Dst
    Move disc 1 from Aux to Src
    Move disc 2 from Aux to Dst
    Move disc 1 from Src to Dst

    或许这样的输出还看不出什么。如果你在每句代码下添加一句打印的代码,结果就很让人迷糊了,如:

            var haoni = function(disc, src, aux, dst){
                document.write('111<br/>');
                if(disc > 0){
                    document.write('222<br/>');
                    haoni(disc - 1, src, dst, aux);
                    document.write('333<br/>');
    
                    document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst + '<br/>');
    
                    document.write('444<br/>');
                    haoni(disc -1, aux, src, dst);
    
                    document.write('555<br/>');
                }
                document.write('666<br/>  ');
            };
    
            haoni(3, 'Src', 'Aux', 'Dst');
    View Code

    结果如下:

    111
    222
    111
    222
    111
    222
    111
    666
    333
    Move disc 1 from Src to Dst
    444
    111
    666
    555
    666
    333
    Move disc 2 from Src to Aux
    444
    111
    222
    111
    666
    333
    Move disc 1 from Dst to Aux
    444
    111
    666
    555
    666
    555
    666
    333
    Move disc 3 from Src to Dst
    444
    111
    222
    111
    222
    111
    666
    333
    Move disc 1 from Aux to Src
    444
    111
    666
    555
    666
    333
    Move disc 2 from Aux to Dst
    444
    111
    222
    111
    666
    333
    Move disc 1 from Src to Dst
    444
    111
    666
    555
    666
    555
    666
    555
    666
    View Code

    如果你仔细看下打印的结果,你会发现结果很有意思,这里可以自己发现哦-_-!。

    思考问题-查找资料

     细心的人应该会看出上面的疑问。为什么会这样:

    666
    333   //为什么666之后会是333
    Move disc 1 from Src to Dst

    这里就要说点其他的了。

    JavaScript中有一个重要的东西叫“执行环境”。执行环境定义了变量或者函数有权访问的其他数据,决定了他们各自的行为。而每个执行环境都有一个和他有关的变量对象,环境中定义的所有变量和函数都保存在这个对象中。每个函数都有自己的执行环境。当执行流进入一个函数的时候。函数的执行环境会被推入一个环境栈中。而函数执行之后栈会将他的执行环境弹出,把控制权返回给之前的执行环境。

    这段话摘自:《JavaScript高级程序设计》。所以上面的问题就有了解答。

    从一个例子解答问题

    我们先来看一个小例子:

            (function(num){
                if(num > 1){
                    console.log('11');
                    arguments.callee(num-1);
                    console.log('22');
                }
            }(3));

    结果:

    11
    11
    22
    22

    根据上面资料的介绍,这个结果也就很好理解了。当第一次执行的时候num是3,进入if判断打印‘11’。然后调用自身,这个时候函数(这里叫A)会进入另外一个函数(这里叫B)而新的执行环境也会进来(虽然另外一个函数还是自身)。结果进入到新的函数之后再次if判断,结果符合条件就再次打印‘11’,然后执行环境再次被改变(这里叫C)。在新的执行环境内发现if不在满足,退出当前的执行环境(这里是从C退出),把控制权交给之前的执行环境(这里交给的是B不是A,然后打印‘22‘),而B在这时也不在满足条件就在交给最初的A,然后A继续接下来的执行打印’22‘。

    因此

    这样上面的结果也就比较好理解了,只是函数里面有两个递归,当第一个递归把控制权交回到最开始的时候是第二个递归的开始,所以就会看到打印的结果跳来跳去,所以使用递归的时候一定要注意。

  • 相关阅读:
    Vue常用特性-表单基本操作和表单修饰符
    Tab选项卡
    Vue模板语法
    Vue基本使用
    Vue概述
    Express框架
    模板引擎artTemplate
    MongoDB增删改查操作
    数据库概述及环境搭建
    请求响应原理及HTTP协议
  • 原文地址:https://www.cnblogs.com/Dn9x/p/3517625.html
Copyright © 2020-2023  润新知