2016-11-17 1 views
1

Следующий фрагмент кода предназначен для циклического перемещения по массиву (который содержит 4 объекта); с каждой итерацией предполагается создать изображение карты. После 4 итераций каждая сторона должна иметь по 4 карты.Почему я вижу только последнее загруженное изображение, используя этот код JavaScript?

Проблема: отображается только последнее изображение (т. Е. Элемент myHeroCards [3] .image). Поле предупреждения отображается последовательно с каждой итерацией: «0», «1», 2 ».

Связанные сообщения ссылаются на проблемы с использованием« для циклов »для шага, хотя массив, но я не думаю это проблема, потому что я могу получить любое изображение, которое будет отображаться, заменив x на значение 0-3.

Я подозреваю, что взаимодействие с тем, как работает onload, и как вычисляются операторы цикла, . подробности

function startingCardLayout(){ 
    var nextHeroCard=0; 
    var x=0; 
    for (i=0;i<=2;i++){ 
     myHeroCards[x].image.onload = function(){ctx.drawImage(myHeroCards[x].image,(xFirstCol+(x*xColInc)),100,xCardSize,yCardSize);} 
     alert(x); 
     x=x+1; 
    } 
} 

ответ

0

Вы назначая каждому из этих элементов массива функции, определенные здесь:

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

Здесь указывается переменная x, которая определяется вне функции. Это означает, что при изменении переменной x внутри цикла for эти функции будут ссылаться на значение x, а не на старое значение. Это объясняет, почему вы видите только последнее изображение: все изображения рисуются в одном и том же месте, и появляется только последний (тот, что сверху). Это также объясняет, почему вы видите правильные значения 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); 
Смежные вопросы