简体   繁体   English

学习Javascript,为什么这两个函数的行为不同?

[英]Learning Javascript, why do these two functions behave differently?

Learning Javascript and can't figure out why these two functions are different. 学习Javascript并无法弄清楚为什么这两个函数不同。 I saw this example (I added names to the functions): 我看到了这个例子(我在函数中添加了名称):

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

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

I see that a function that calls alert is being returned. 我看到正在返回一个调用alert的函数。 So I thought, why not just return it directly: 所以我想,为什么不直接返回它:

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

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

This ends up alerting 'undefined.' 这最终警告'未定义'。 I understand that it's because it's trying to access txt[3] because after one second the loop has finished and i has been set to 3, but I don't understand how the original setup avoided this problem. 我明白这是因为它试图访问txt [3],因为一秒钟后循环结束并且我已经设置为3,但我不明白原始设置是如何避免这个问题的。

You need to read up about closures. 你需要阅读有关闭包的内容。 See this answer How do JavaScript closures work? 查看此答案JavaScript闭包如何工作? to understand them. 了解他们。

Example 1 例1

The closures execute the script instantly and also allow you to pass a parameter inside which is stored and remains stored inside that function. 闭包立即执行脚本,并允许您传递存储的参数,并保存在该函数中。 parameter==param 参数== PARAM

(function(param){})(parameter)

In your example the function returns another function which will be executed by setTimeout. 在您的示例中,该函数返回另一个将由setTimeout执行的函数。

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

And as you passed the parameter previously to the function it will return the right value. 当您将参数先前传递给函数时,它将返回正确的值。

Example 2 例2

The setTimeout is called 3 times very fast but the parameter is not stored anywhere so it takes the last value know from txt & i and as the loop is ended before the setTimeout is executed the value is 3 setTimeout被调用3次非常快,但参数不存储在任何地方,因此从txt&i得到最后一个值,并且在执行setTimeout之前循环结束,值为3


basically in the first example you store every txt[i] inside each function you create with those closures. 基本上在第一个例子中,您将每个txt [i]存储在您使用这些闭包创建的每个函数中。

In the second one you don't store the txt[i]'s anywhere. 在第二个你不存储txt [i]的任何地方。 you just tell the setTimout function to alert txt[i], which after 1second is the last one created by the for loop. 你只需告诉setTimout函数提醒txt [i],在1秒之后是for循环创建的最后一个。

In the first version, txt[i] has been bound to a new variable, msg , which is a different location for each function being created. 在第一个版本中, txt[i]已绑定到一个新变量msg ,它是每个正在创建的function的不同位置。

In the second version, i is the same location for each of the function s because i 's scope is further up; 在第二个版本中, i是每个function的相同位置,因为i的范围更进一步; there isn't a new i variable being created each time through the loop. 每次循环都没有创建新的i变量。

This is a concurrency problem. 这是一个并发问题。

setTimeout creates a "thread" for each execution, but won't evaluate the function until the timeout expires. setTimeout为每次执行创建一个“线程”,但在超时到期之前不会评估该函数。

so, after a second, when the first timeout expires, your for loop has ended (with i having 3 as value), so accessing the txt[i] returns undefined. 所以,在一秒钟之后,当第一个超时到期时,你的for循环结束了( i值为3),所以访问txt[i]返回undefined。 Try printing the value of i inside the function with console.log 尝试使用console.log在函数内打印i的值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM