我试图解开代码
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
从这里http://bonsaiden.github.com/JavaScript-Garden/#function.closures
我理解这种方法:
for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
有人可以通过解释第一个来帮助我吗?
我将尝试解释我如何理解第一个,
first i is 0,
setTimeout is called,
self calling function "function(e)" is called with i=0,
Im stuck!! what happens when this function returns a function?
答案 0 :(得分:4)
所有第一个返回的函数将在超时发生后调用。
它的目的是为for循环的每次迭代创建一个子范围,以便每次迭代都不会覆盖递增i
。
更多解释:
让我们把它分成两个不同的部分:
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
这是第一篇:
for(var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i); //9-9
},1000);
}
现在,当你运行这个循环时,你将总是得到包含9而不是0到9的console.log()。这是因为每个setTimeout都使用与i
相同的引用。
如果将setTimeout的一部分包装在匿名函数中,它会为每次迭代创建一个范围,允许每个setTimeout拥有它自己的i
值。
for(var i = 0; i < 10; i++) {
setTimeout((function(i) {
return function() {
console.log(i); // 0-9
}
})(i), 1000)
}
setTimeout中的外部函数立即执行,第一次迭代的i为0,第二次为1,等等。然后该函数返回一个函数,该函数是setTimeout使用的函数。正在使用i
的不同值为循环的每次迭代生成并返回一个函数。
答案 1 :(得分:2)
两者最终得到相同的结果:使用要调用的函数调用setTimeout,该函数在控制台上写入0到9之间的数字。两者都使用嵌套函数将i的当前值放入闭包中,因此最终不会记录10 9。
第一个代码选择让函数返回setTimeout将调用的函数。第二个更改嵌套顺序,以便关闭函数调用setTimeout本身。净效果是一样的。
除了风格上的原因和个人选择之外,我没有理由选择其中一种。
答案 2 :(得分:1)
&#34;请查看更新后的问题,说明我感到困惑的地方&#34;
好的,这是长的解释。请记住,setTimeout()
的第一个参数需要是在指定延迟后要执行的函数的引用。最简单的情况是命名一个在别处定义的函数:
function someFunc() {
console.log("In someFunc");
}
setTimeout(someFunc, 100);
注意someFunc
将setTimeout
作为参数传递给setTimeout(someFunc(), 100); // won't work for someFunc() as defined above
时没有括号,因为需要引用函数本身。对比:
someFunc()
使用括号,调用 setTimeout
并将其返回值传递给someFunc()
。但是我上面对undefined
的定义并没有明确地返回一个值,所以它隐含地返回setTimeout(undefined, 100)
- 这就像说someFunc()
。
但如果更改undefined
以返回函数而不是返回function someFunc() {
return function() {
console.log("In the function returned from someFunc");
};
}
,则会有效:
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
所以现在(最后)我们来看你问题的代码:
someFunc(i)
不是按名称引用函数并将其称为(function(e) {})(i)
,而是定义匿名函数并立即将其作为setTimeout()
调用。该匿名函数返回另一个函数,它返回的函数成为e
的实际参数。当时间到时,它将返回将要执行的函数。因为返回的(内部)函数是在(外部)匿名函数的范围内定义的,所以它可以访问{{1}}参数。