我以为我用Javascript理解了闭包,但显然我没有。以下代码不起作用。如何在延迟1秒后打印出控制台中从0到9的所有数字?目前它只打印“未定义”十次。带有Javascript回调的闭包
注意:我不想寻找一个简单的锻炼来延迟打印数字。这个问题是关于理解闭包。
<script>
for(var i=0;i<10;i++){
setTimeout(function(i){console.log(i)}, 1000)
}
</script>
我以为我用Javascript理解了闭包,但显然我没有。以下代码不起作用。如何在延迟1秒后打印出控制台中从0到9的所有数字?目前它只打印“未定义”十次。带有Javascript回调的闭包
注意:我不想寻找一个简单的锻炼来延迟打印数字。这个问题是关于理解闭包。
<script>
for(var i=0;i<10;i++){
setTimeout(function(i){console.log(i)}, 1000)
}
</script>
闭包是在JavaScript中很重要,但要了解你是closing
正是在这一点很重要。重做你当前的代码(种类)。
function(){
var i;
for(i=0;i<10;i++){
setTimeout(function(){
console.log(i);
}, 1000);
}
}
在这个例子中,你的代码基本上是关闭了var i;
,这意味着当定时器运行时,它会读取该的var i;
值并打印出来。在这种情况下,如您所见,定时器运行时,循环已完成,值为10
。
你想要做的是创建一个新的函数范围,在特定的时间捕获i
的值。
function(){
var i;
for(i=0;i<10;i++){
(function(iInner){
setTimeout(function(){
console.log(iInner);
}, 1000);
})(i);
}
}
这个例子将创建一个新的匿名函数,然后在循环立即调用它,并传递的i
当前值到它,所以,当你的计时器读取iInner
,它会读取这可是价值传递给函数,而不是来自var i;
的值。如果需要,您也可以拨打iInner
i
,但为了清晰起见,我使用了两个不同的名称。
还有一些助手可以使用,例如.bind
,它们本质上会自动为您创建一个新的匿名函数,并传递像这样的参数。
function(){
var i;
for(i=0;i<10;i++){
setTimeout(function(iInner){
console.log(iInner);
}.bind(null, i), 1000);
}
}
<func>.bind
将采取i
的值,并返回调用时通过对<func>
那些ARGS一个新的功能,您就不必创建嵌套的另一层。
您已经定义了回调函数取参数i
,这是掩盖在声明for循环closurable i
。因此,将其更改为:
<script>
for(var i=0;i<10;i++){
setTimeout(function(){console.log(i)}, 1000)
}
</script>
编辑:对不起,我不看你的问题的一般意图。就封闭方式而言,函数对象捕获对函数体内引用的封闭范围中的任何变量的引用,该引用不绑定到主体内的任何局部变量(参数或显式var
声明) 。这就是为什么你的原始尝试不起作用; i
绑定到本地参数。
功能对象不会不捕获值该合拢变量具有在被定义的功能的时间;它捕获了一个参考它。因此,您无法迭代单个变量(我正在讨论在for循环中声明的var i
),意图是为每个后续函数定义关闭值。价值观没有关闭;变量是。
但是,您可以通过关闭一个临时本地来有效地关闭一个值,该临时本地具有您要在定义该函数时捕获的值。它需要创建一个新的功能范围和界定范围内的closuring功能,围绕本地(函数参数)closuring有你想要的值:
<script>
for (var i_outer = 0; i_outer < 10; ++i_outer)
setTimeout((function(i_inner) { return function() { console.log(i_inner); }; })(i_outer), 1000);
</script>
这是你怎么做。您创建了一个IIFE(立即调用的函数表达式),该函数返回一个打印到控制台的函数。记住我的价值,应该被内在的功能所吞噬,通过将它作为一个参数来传递。
setTimeout需要一个“函数”作为第一个参数,这就是我们从IIFE返回函数的原因。
for(var i=0;i<10;i++){
setTimeout((function(i) {
return function() {
console.log(i);
}
})(i), 1000)
}
感谢
不!这只是打印10次。这就是为什么我们需要关闭。 – 2014-12-06 20:46:36