Почему это значение возвращает true в конце цикла, а затем false в его начале?

#javascript #html5-canvas

Вопрос:

Рассмотрим следующую функцию, которая должна рисовать изображение на холсте по частям, кэшировать эти фрагменты, а затем в следующем цикле проверять эти кэшированные фрагменты, чтобы убедиться, что мы ничего не рисуем больше одного раза. Если консоль.журнал подтверждает, что кэшированный массив чанков никогда не очищается, почему при pixels.data == cachedImage[y][x] печати результата он всегда возвращается false , но после обновления кэша он сообщает как true ?

 async function temp() {
   const DIVIDE = 8;
   for(let y = 0; y < DIVIDE; y  ) {
       if(cachedImage[y] == undefined) {cachedImage[y] = []; console.log(y);}
       for(let x = 0; x < DIVIDE; x  ) {
           let widthChunk = (drawBuffer.width)/DIVIDE;
           let heightChunk = (drawBuffer.height)/DIVIDE;
           let pixels = ctx.getImageData(x*widthChunk,y*heightChunk,widthChunk-1,heightChunk-1);
           let pixeldata = pixels.data;
           debugBox3.innerHTML = (cachedImage[y][x] == pixels.data); // always "false"
           if(pixels.data == cachedImage[y][x]) {
           } else {
               cachedImage[y][x] = pixels.data;
               ctxFinal.putImageData(pixels,x*widthChunk,y*heightChunk)
           }
           debugBox4.innerHTML = (cachedImage[y][x] == pixels.data); // always "true"
       }
   }
}
await temp();
 

(полный файл доступен здесь)

Комментарии:

1. Вы спрашиваете, почему cachedImage[y][x] == pixels.data значение true сразу после установки cachedImage[y][x] = pixels.data; ???

2. Я спрашиваю, почему, когда цикл повторяется, cachedImage[y][x] == pixels.data внезапно становится false .

3. Потому что это новое местоположение в массиве? Это не data массив, поэтому ваше сравнение должно измениться.

4. Этого не должно быть, старое местоположение должно быть заменено.

5. Массивы являются объектами — поэтому ImageData.data возвращает ссылку на объект массива. Вы не можете проверить эквивалентность объектов с помощью простых операторов эквивалентности ( === ).

Ответ №1:

Предположим, что следующий код:

 let object1 = { key: 'value' }

var object2 = { key: 'value' }
 

Можно было бы подумать, что object1 == object2 это правда, но это не так. Почему? Потому что object1 и object2 являются просто ссылками на объекты — то есть на независимые объекты.

Однако, если мы расширим код:

 let object1 = { key: 'value' }

var object2 = { key: 'value' }

object1 = object2
 

Теперь мы установили переменную object1 равной ссылке на object2. Мы не скопировали object2 .

Следовательно object1 == object2 , теперь true .

Когда вы говорите cachedImage[y][x] = pixels.data; , что на самом деле cachedImage[y][x] ссылаетесь на pixels.data . Только тогда оно равно пикселям.данные (которые также являются просто ссылкой).

Это несколько знакомо с указателями в c, см.: https://www.sitepoint.com/how-javascript-references-work .

Комментарии:

1. Итак, как бы мне установить содержимое cachedImage[y][x] в значение pixels.data ?

2. используйте Object.is (obj1, obj2) вместо obj1===obj2

3. если бы вы действительно хотели, вы могли бы сказать cachedImage[y][x] = { … пиксели. данные } (если пиксели. данные — это объект, иначе используйте […пикселей. данные ]) но это было бы ужасно неэффективно по соображениям памяти