2013-10-28 40 views
0

Just Learn JS。 在我的脑海里,功能的setTimeout代码区域应该像正常的,但它不是,EXP:setTimeout()如何工作JS

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的,这将是很好。 有人知道为什么吗?

回答

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将引用与您预期不同的对象。
+0

明白了,thxxxxxxxxxx – jfw10973

0

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

因此,当您稍后设置它时,代码继续外部您的“超时循环”并进入警报。在此期间,循环只做一个周期,result只得到10

加入你能做什么:

+3

'arguments.callee'不被弃用,但在严格模式下被禁止。 –

0

鉴于:

  1. arguments.callee的不喜欢的(并且不会被弃用)
  2. 有名函数表达式have their own issues
  3. 似乎是一个目标,这里不是创建一个全局变量的存在运行超时

考虑在IIFE内部声明函数(调整我认为你想要的 - 一个lert 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)); 

注意,没有必要为其他块(除非你想返回比undefined其他东西)。

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

setTimeout(foo, 100, --j); 

因此可以节省额外的函数对象。