为什么这个递归函数没有停止?

时间:2014-04-04 14:34:38

标签: javascript recursion

我试图创建一个递归函数来迭代数据集,但它没有正确地突破并且是无限的

jsfiddle 显示的代码

var data = [{a: 1,b: 1}, {a: 2,b: 2}],z = 0;

function some(a, b, cbk) {
    console.log(a + ':' +b);
    cbk();
}

function main() {
    var cbk = function () {
        if (z < data.length) {
            main();
        } else {
            console.log('end');
        }
        z++;
    }
    some(data[z].a, data[z].b, cbk);
}
main();

为什么这是一个无限循环?

3 个答案:

答案 0 :(得分:1)

我被告知要取消删除这个,因为它是负责任的,虽然我越来越讨厌,我发现我已经注意到了我的错误并做到了这一点。

var data = [{
    a: 1,
    b: 1
}, {
    a: 2,
    b: 2
}],
    z = 0;

function some(a, b, cbk) {
    console.log(a + ':' +b);
    cbk();
}

function main() {
    var cbk = function () {
        z++;
        if (z < data.length) {
            main();
        } else {
            console.log('end');
        }

    }
    some(data[z].a, data[z].b, cbk);

}

main();

答案 1 :(得分:1)

jsFiddle Demo

这里有一些事情使得递归失败涉及迭代控制。从z = 0开始,与.length进行比较,z需要在条件检查if( z < .length )之前预先增加。

原因是在递归路径之后,z从不递增,因此递归是无限的,导致页面锁定。因此,z需要在递归调用发生之前进行处理,最好在与.length进行比较之前进行处理。

在原始版本中,这不仅发生在if语句之后,而且发生在递归调用之后。修复此迭代器将修复递归。

if (++z < data.length) {

答案 2 :(得分:0)

我不知道你读代码是多么流利,但我试图将线性递归的概念分解为我想象的通用方式

function recurse(data, /* fns */ step, worker, joiner, /* vals */ first, empty) {
    function recursor(data, current) {
        var result = worker(data, current), // do work with current iteration
            next = step(data, current);     // find the next iteration
        if (next !== null)                  // if found
            return joiner(                  //   return
                result,                     //   the result from this time
                recursor(data, next)        //   + the result from next time
            );
        else                                // if not found
            return joiner(                  //   return
                result,                     //   just this result
                empty // this join is helpful for joining arrays/objects/etc
            );
    }
    return recursor(data, first); // start it
}

所以,一个基于你正在做的事情的例子

var data = [{a: 1,b: 1}, {a: 2,b: 2}];

function init(data) {
    function logger(data, i) { // a function describing what to do
        var e = data[i];       // with this iteration
        console.log(e.a + ':' + e.b);
        return e.a;
    }
    function step(data, i) {   // a function describing how to find
        i = i + 1;             // the next iteration
        if (i < data.length) return i;
        return null; // null = end
    }
    function add(a, b) {       // a function describing how to join
        return a + b;          // two iterations together
    }
    return recurse(data, step, logger, add, 0, 0);
}

init(data); // run everything safely in it's own closure
/*
  1:1
  2:2
  3 // === 1 + 2 + 0, from return of logger and result of add
*/

当然,在实践中你可以在很多方面做到这一点,而不是为每件事做一个函数,而step通常可以简化得那么多,你不需要var对于resultnext,因为您不必为if测试缓存任何内容。