递归中的闭包

Closures in recursion

本文关键字:闭包 递归      更新时间:2023-09-26

我在javascript中有这两个递归函数。第一个函数按从右到左的顺序返回输入数字第二个函数按从左到右的顺序返回它们。

function first(n){
    if(n > 0){
        m = Math.floor( n/10 );
        v = ( n - m * 10 ) + " " + first(m);
        return v;
    }
    return "";
}

function second(n){
    if(n > 0){
        m = Math.floor( n/10 );
        v = second(m) + " " + ( n - m * 10 );
        return v;
    }
    return "";
}

第一个函数的结果是

7 6 1 

第二个函数的结果是

1 16 167

但我预料到这个

1 6 7 

我在PHP和JAVA中测试了类似的代码,它运行得很好。问题可能出在Javascript的闭包上。但是我不知道该怎么解决。

非常简单:您使用的是隐含的全局变量:

function second(n)
{
    if(n > 0)
    {
        m = Math.floor( n/10 );
        //m is changing here ------''will use lowest value of m
        v = second(m) + " " + ( n - m * 10 );
        return v;
    }
    return "";
}

修复方法是:

function second(n)
{
    if(n > 0)
    {
        //make declare it in the scope itself
        var m = Math.floor( n/10 );
        v = second(m) + " " + ( n - m * 10 );
        return v;
    }
    return "";
}

这仍然会给您留下邪恶隐含的全局v。如果我是你,我会在本地申报v,也是

function second(n)
{
    var m, v = '';
    n = +(n);//coerce to number
    if (n > 0)
    {
        m = Math.floor(n/10);
        v = second(m) + ' '+ (n-m*10);
    }
    return v;
}

此功能按预期工作
这个问题实际上与闭包无关,但它是由JS解析表达式/名称的方式引起的
再加上JS处理递归函数的方式,就可以得到简单明了的输出。

JS还没有真正的递归调用堆栈。上次我检查时,递归调用实际上是短路的(~=goto的)。我记得读过Douglas Crockford关于这个主题的文章,关于它与调用堆栈有关
尽管ES5的严格模式确实引入了TCO,并且它应该在2013年底前实现(ES6-和谐)。我在这里链接了几个网站,如果你想阅读更多关于此事的信息