0

刚学JS。在我看来,函数 setTimeout 代码区域应该正常工作,但事实并非如此,exp:

var result = 0;
(function (i){
if(i > 0){
    result = result + i;
    i = i - 1;
    setTimeout("arguments.callee(" + i + ")",100);//arguments.callee(i);
}
else if(i == 0)
    return;
}(10));
alert(result);

我希望它警报 55 而不是 10,如果删除 setTimeout ,它会很好。有人知道为什么吗?

4

3 回答 3

0

鉴于:

  1. arguments.callee 不被喜欢(并且未被弃用)
  2. 命名函数表达式有自己的问题
  3. 这里似乎有一个目标,即不创建全局变量来运行超时

考虑在 IIFE 中声明函数(根据我认为你想要的进行调整 - 10 次迭代后的警报显示结果为 10):

var result = 0;

(function (i){
  function foo(j) {
    if(j > 0){
      ++result;
      setTimeout(function(){foo(--j)},100);
    } else {
      alert('Result: ' + result);
    }
  }
  foo(i);
}(10));

请注意,不需要else块(除非您想返回 以外的内容undefined)。

哦,请注意,在 ES5 和其他支持它的浏览器中(不是 IE < 9),您可以在调用 setTimeout 时传递参数:

  setTimeout(foo, 100, --j);

所以你保存了一个额外的函数对象。

于 2013-10-28T05:21:34.877 回答
0

尝试

var result = 0;
(function (i, callback) {
    if (i > 0) {
        result = result + i;
        i = i - 1;
        var callee = arguments.callee;
        setTimeout(function () {
            callee(i, callback)
        }, 100);
    } else if (i == 0) {
        callback();
    }
}(10, function () {
    alert(result);
}));

演示:小提琴

为什么?
您的方法存在多个问题

  1. setTimeout 是异步的,这意味着您的警报将在添加操作完成之前触发 - 一种解决方案是使用回调方法,一旦添加完成就会执行,如上所示
  2. 当您将字符串传递给setTimeout它时,它将在全局范围内执行,即arguments.callee将引用与您期望的对象不同的对象。
于 2013-10-28T03:40:50.913 回答
0

因为setTimeout异步的,简单来说意味着它被安排在以后执行。JS 不会等待它(不会停止该行的代码),而是运行后续代码。

因此,当您稍后设置它时,代码会在您的“超时循环”之外继续并进入警报。在这段时间内,循环只做了一个循环,并且result只增加了 10 个。

你可以做什么:

于 2013-10-28T03:39:31.033 回答