0

学习Javascript,无法弄清楚为什么这两个功能不同。我看到了这个例子(我在函数中添加了名称):

var txt = ["a","b","c"];

for (var i = 0; i < 3; ++i ) {    
    setTimeout((function myBind(msg) { 
      return function myAlert() { alert(msg); } 
    })(txt[i]), 1000);        
}​

我看到正在返回一个调用警报的函数。所以我想,为什么不直接返回它:

var txt = ["a","b","c"];

for (var i = 0; i < 3; ++i ) {    
    setTimeout( function() { alert(txt[i]);} ,1000);        
}​

这最终会警告“未定义”。我知道这是因为它试图访问 txt[3] 因为一秒钟后循环完成并且 i 已设置为 3,但我不明白原始设置如何避免此问题。

4

4 回答 4

1

您需要阅读有关闭包的信息。请参阅此答案JavaScript 闭包如何工作?了解他们。

于 2013-08-23T02:47:23.143 回答
1

示例 1

闭包会立即执行脚本,并且还允许您在其中传递一个参数,该参数存储并保持存储在该函数中。参数==参数

(function(param){})(parameter)

在您的示例中,该函数返回另一个将由 setTimeout 执行的函数。

(function(param){
 return function(){
  alert(param)
 }
})(parameter)

当您之前将参数传递给函数时,它将返回正确的值。

示例 2

setTimeout 被快速调用 3 次,但参数未存储在任何地方,因此它采用从 txt & i 知道的最后一个值,并且在执行 setTimeout 之前结束循环,值为 3


基本上在第一个示例中,您将每个 txt[i] 存储在使用这些闭包创建的每个函数中。

在第二个中,您不会将 txt[i] 存储在任何地方。您只需告诉 setTimout 函数提醒 txt[i],它在 1 秒后是 for 循环创建的最后一个。

于 2013-08-23T02:59:14.033 回答
0

这是一个并发问题。

setTimeout 为每次执行创建一个“线程”,但在超时到期之前不会评估该函数。

因此,在一秒钟后,当第一个超时到期时,您的 for 循环已经结束(i值为 3),因此访问txt[i]返回未定义。尝试打印i函数内部的值console.log

于 2013-08-23T02:50:32.670 回答
0

在第一个版本中,txt[i]已绑定到一个新变量 ,msg这是每个function正在创建的不同位置。

在第二个版本中,i每个functions 的位置都相同,因为is 的范围更远;i每次循环都不会创建一个新变量。

于 2013-08-23T02:46:59.897 回答