setTimeout()如何在JS上运行

时间:2013-10-28 03:31:58

标签: javascript settimeout

只学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,它会很好。 有谁知道为什么?

3 个答案:

答案 0 :(得分:0)

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

因此,当您稍后设置它时,代码会继续之外您的“超时循环”并进入警报。在此期间,循环仅执行一个循环,result仅添加了10。

你能做什么:

答案 1 :(得分: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);
}));

演示:Fiddle

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

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

答案 2 :(得分:0)

鉴于:

  1. arguments.callee不喜欢(并且不被弃用)
  2. 命名函数表达式have their own issues
  3. 这里似乎没有创建一个全局变量来运行超时的目标
  4. 考虑在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);
    

    所以你保存了一个额外的功能对象。