[英]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.