递归堆栈 - Javascript

时间:2015-05-31 12:43:33

标签: javascript recursion

我在Javascript中尝试这个递归的事情,并发现数字以错误的顺序打印出来(Desc,而我期待着Asc)。为什么会这样,我怎样才能看到这个过程?

(function hi(x) {
    if (x > 1000) {
        return;
    } else {
        x+=1;
        setTimeout(hi(x), 100000);
        console.log(x);
    }
})(4)

2 个答案:

答案 0 :(得分:5)

将您的代码更改为:

(function hi(x) {
    if (x > 1000) {
        return;
    } else {
        x+=1;
        setTimeout(function (){hi(x);}, 100);
        console.log(x);
    }
})(4)

改变就在这里:

function (){hi(x);}

这:

 setTimeout(hi(x),

立即调用该函数。你不想要那个。

你想要一个功能,它将在100000毫秒后运行hi(x)

答案 1 :(得分:2)

虽然传递给setTimeout的第一个参数是一个函数,但它不是。

当你这样做时:

setTimeout(hi(x), 100000);

意思是:

  1. 评估表达式hi(x)以获取其值
  2. 100000ms后,如果上一步的值为

    • 可调用,调用它(带参数,如果通过)
    • 否则评估它(类似于eval
  3. 所以它等于:

    var ret = hi(x);
    setTimeout(ret, 100000);
    

    显然ret不是你的函数hi,而是它的返回值 - undefined。所以setTimout(undefined, 100000)实际上没有任何意义 - {100}之后eval(undefined)

    剥离出来,你的代码等于:

    (function hi(x) {
        if (x > 1000) {
            return;
        } else {
            x+=1;
            hi(x);
            console.log(x);
        }
    })(4)
    

    这是什么?是的,同步递归函数调用。这就是你在控制台中看到结果的原因,而不是你期望的那样。

    解决方案,除了将其包装在匿名函数中之外:

    setTimeout(function () {
        hi(x);
    }, 100000);
    

    或者,您也可以将额外的参数传递给setTimeout

    setTimeout(hi, 100000, x);
    

    延迟后传递给setTimout的参数将在调用时传递到hi