for 循环和词法环境中的闭包
简单的情况:我想加载几个具有共同名称和后缀的图像,例如:image0.png、image1.png、image2.png ... imageN.png
我正在使用一个简单的 for 循环:
var images = [];
for (var i=1; i<N; i++) {
images[i] = new Image();
images[i].onload = function () {
console.log("Image " + i + " loaded");
};
images[i].src = "image" + i + ".png";
}
我在做什么进入控制台是:
Image N loaded
Image N loaded
Image N loaded
...
Image N loaded
但我想要的应该是这样的:
Image 0 loaded
Image 1 loaded
Image 2 loaded
...
Image N loaded
为什么会发生这种情况? 我怎样才能得到我想要的行为?
Simple case: I want to load several images which have a common name and a suffix, e.g: image0.png, image1.png, image2.png ... imageN.png
I'm using a simple for loop:
var images = [];
for (var i=1; i<N; i++) {
images[i] = new Image();
images[i].onload = function () {
console.log("Image " + i + " loaded");
};
images[i].src = "image" + i + ".png";
}
What I'm getting in the Console is:
Image N loaded
Image N loaded
Image N loaded
...
Image N loaded
But what I want should be like this:
Image 0 loaded
Image 1 loaded
Image 2 loaded
...
Image N loaded
Why is this happening?
How can I get my desired behavior?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
函数内的
i
在函数执行时计算,而不是在将其分配给onload
时计算。当任何onload
函数触发时,您的 for 循环已经完成,因此所有函数都会看到最终值N
。要捕获
i
的当前值,您需要将其作为参数传递给另一个函数,在该函数中可以将其捕获为局部变量:这有效,因为每次调用
captureI
>,为该captureI
实例创建一个新的局部变量。本质上,您正在创建N
个不同的变量,并且每个onload
函数捕获该变量的不同实例。The
i
inside your function is evaluated when the function is executed, not when you assign it toonload
. Your for loop has already completed by the time any of youronload
functions fire, so all of them see the final valueN
.To capture the current value of
i
, you need to pass it as a parameter to another function where it can be captured as a local variable:This works because every time you call
captureI
, a new local variable is created for that instance ofcaptureI
. In essence, you are creatingN
different variables and eachonload
function captures a different instance of the variable.您可以将其包装在闭包中,以避免使用
i
变量(这是一个循环变量)并因此发生变化:这演示了
i
(这是一个循环变量)和更改,以及j
,这是一个函数绑定参数,不会更改。请参阅此处的 jsfiddle:
You can wrap it in a closure to avoid to use
i
variable, which is a loop variable and thus changes:This demonstrates the difference between
i
, which is a loop variable and changes, andj
, which is a function-bound parameter, which doesn't change.See the jsfiddle here:
您的循环计数器变量已被覆盖。查看此常见问题解答条目,其中准确解释了发生这种情况的原因以及如何解决该问题。
Your loop counter variable has been overwritten already. Check out this FAQ entry explaining exactly why it happens and how to work around the issue.
由于变量
i
是在循环范围之外声明的,因此它在循环完成后保留其最终值。然后,您创建的匿名函数都会绑定到该变量,并且当调用它们时,它们都会获得相同的最终值N
。这个问题。
Since the variable
i
is declared outside the scope of the loop, it retains its final value after the loop has completed. The anonymous functions you're creating then all bind to this variable, and when they're called, they all get the same final value ofN
.There's a good discussion of this in this question.