为什么我只使用此JavaScript代码查看上次加载的图像?

时间:2016-11-17 19:46:55

标签: javascript arrays function for-loop closures

以下代码片段用于遍历数组(包含4个对象);每次迭代都应该产生卡片的图像。经过4次迭代后,每行应该有4张卡。

问题:只显示最终图像(即myHeroCards [3] .image的元素)。警报框按顺序显示每次迭代:" 0"," 1",2"。

相关帖子指的是使用" for循环的问题"通过一个数组;但我不认为这是问题所在,因为我可以通过将{% endif %}替换为0-3来显示任何给定的图像。

我怀疑与onload如何工作以及如何评估循环语句的交互,但我对这些细节感到困惑。

x

1 个答案:

答案 0 :(得分:0)

您为这些数组元素分配了一个定义的函数:

function () {
      ctx.drawImage(myHeroCards[x].image,
                   (xFirstCol+(x*xColInc)),
                   100,xCardSize,yCardSize
      );
}

这引用了变量x,它是在函数外部定义的。这意味着当您更改for循环中的变量x时,这些函数将引用x new 值而不是旧值。这就解释了为什么你只能看到最后一张图像:所有图像都在完全相同的位置绘制,只有最后一张图像(顶部的图像)显示出来。它还解释了为什么你在循环中看到x的正确值以及为什么它在你对数字进行硬编码时它的工作原理 - 在循环内部,一切都很好,但是在循环结束后所有的功能你已创建的内容共享x的相同值。

要解决此问题,您可以使用此技术创建变量x的本地副本:

myHeroCards[x].image.onload = function(x) {
       return function () {
           ctx.drawImage(myHeroCards[x].image,
               (xFirstCol+(x*xColInc)),
               100,xCardSize,yCardSize
           );
       }
} (x);

这里,函数内部的变量x是函数外部变量x的当前值的新副本。

一般来说,如果您正在使用JavaScript中的循环并希望在循环内创建一些引用循环期间变化的函数(此处为x,但更常见的是,某些东西)像循环计数器一样,你可能想要使用双重嵌套函数习语:

 var thingy = function(values, i, care, about) {
     return function() {
         // Code that uses values I care about
     }
 } (values, i, care, about);