带闭包的 JavaScript 作用域:帮助我理解
运行以下代码:
for (var i=0; i<3; i++) {
setTimeout( function() { console.log(i); } , 500 );
}
输出“3”三次。它输出 i
的最终值,而不是创建内部函数时 i
的值。
如果我希望输出为1、2和3,我该如何编写这段代码?如何让它使用定义函数时的 i 值而不是其最终值?
Running the following code:
for (var i=0; i<3; i++) {
setTimeout( function() { console.log(i); } , 500 );
}
Outputs "3" three times. It's outputting the final value of i
as opposed to the value of i
when the inner function is created.
If I want the output to be 1, 2, and 3, how would I write this code? How can I get it to use the value of i
at the time the function is defined as opposed to its final value?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因此,在
setTimeout
时(在我们定义setTimeout
函数时),我们调用以val
作为参数的匿名函数。这为每个函数调用创建了一个闭包,将val
的值存储在我们刚刚调用的函数的范围内。我使用了 self-调用函数,它会立即创建一个闭包。在您提供的代码中,代码创建了一个闭包,但是对于整个代码的更大范围,因此
i
对于整个代码来说是本地的,这意味着在运行时,匿名函数将使用其余代码使用的变量i
。So, at
setTimeout
time (at the time we define the function forsetTimeout
), we're calling the anonymous function takingval
as a parameter. This creates a closure for each function call, storing the value ofval
within the scope of the function we just called. I used a self-invoking function, which creates an immediate closure.In the code you provided, the code creates a closure, but for the larger scope of the entirety of the code, so
i
is local to the whole code, meaning that at run-time, the anonymous function will use the variablei
that the rest of the code uses.显式闭包的现代替代方案(当您有一个双层包装函数时,读起来可能会有点麻烦)是
Function#bind
。一旦您获得支持 对于尚未执行 ECMAScript 第五版的浏览器,您可以说:window
是this
将在函数内部的值(您不需要这里的this
,所以我们只使用默认的全局对象)。如果您只是调用另一个函数/方法,就像这里使用console.log
一样,您可以使用它来完全删除函数表达式:The modern alternative to an explicit closure (which can get a bit hairy to read when you've got a double-wrapped function) is
Function#bind
. Once you've hacked in support for browsers that don't do ECMAScript Fifth Edition yet, you can say:the
window
is the value thatthis
will be inside the function (you don't need athis
here, so we just use the default global object). In the case where you're just calling another function/method, like here withconsole.log
, you can use that to excise the function expression completely:选择:
alternative: