zoukankan      html  css  js  c++  java
  • 一个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‘。

    因此

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

  • 相关阅读:
    HIVE Group by、join、distinct等实现原理
    【1.3】shell基础——调试shell(sh -x)
    sql server无法显示请求的对话框,检索数据失败
    sql server索引操作
    sql server中的alter
    tempdb无法收缩。使用 DBCC FREESYSTEMCACHE 解决
    在从该备份集进行读取时,RESTORE 检测到在数据库 "CISDB" 中的页(0:0)上存在错误。系统断定检查已失败
    【1.2】shell基础——stty erase解决按backspace出现^H的情况
    【1.1】shell基本实践——密码输入三次错误则结束
    (5.3.7)数据库迁移——sql server备份文件的加密解密
  • 原文地址:https://www.cnblogs.com/Dn9x/p/3517625.html
Copyright © 2011-2022 走看看