为什么不是';js图像对象是否被垃圾收集? 我来自C++背景,学习JavaScript。webgl上的Mozilla教程的代码类似于下面的代码(实际代码和底部的链接)。我试图理解为什么“onload”回调函数中的代码总是被执行。在我看来,映像对象实例应该在下面的代码中进行垃圾收集。因此,理论上它可以在加载完成并调用“onload”回调之前被垃圾收集 function foo() { image = new Image(); image.onload = function() { /*stuff to do when image gets done loading */ Console.log(image.width); } image.src = url; }

为什么不是';js图像对象是否被垃圾收集? 我来自C++背景,学习JavaScript。webgl上的Mozilla教程的代码类似于下面的代码(实际代码和底部的链接)。我试图理解为什么“onload”回调函数中的代码总是被执行。在我看来,映像对象实例应该在下面的代码中进行垃圾收集。因此,理论上它可以在加载完成并调用“onload”回调之前被垃圾收集 function foo() { image = new Image(); image.onload = function() { /*stuff to do when image gets done loading */ Console.log(image.width); } image.src = url; },javascript,image,reference,garbage-collection,Javascript,Image,Reference,Garbage Collection,我唯一的想法是使用“image.width”的函数——函数对象必须将图像实例保存在内存中。但这将是一个圆引用,因为该函数只存在于图像对象本身上;函数对象的唯一引用AFAIK是其onload回调属性。所以循环引用(image->onload->function->image->…)应该被垃圾收集 似乎我不明白什么,或者在图像加载和垃圾收集之间存在竞争条件 显示不再可访问的循环引用岛的JS引用应该被垃圾收集 教程链接: 当您指定给image.src时,imageobect将添加到浏览器的内部队列中

我唯一的想法是使用“image.width”的函数——函数对象必须将图像实例保存在内存中。但这将是一个圆引用,因为该函数只存在于图像对象本身上;函数对象的唯一引用AFAIK是其onload回调属性。所以循环引用(image->onload->function->image->…)应该被垃圾收集

似乎我不明白什么,或者在图像加载和垃圾收集之间存在竞争条件

显示不再可访问的循环引用岛的JS引用应该被垃圾收集

教程链接:


当您指定给
image.src
时,
image
obect将添加到浏览器的内部队列中,用于异步加载的所有外部对象。此队列防止在函数返回时对象立即变成垃圾。队列是浏览器管理加载这些对象的过程所必需的——它需要保存正在加载的对象,以便在收到服务器的响应时知道该做什么

加载图像时,其
onload
函数将添加到事件队列中,并且由于它通过
image
变量(以及函数的
this
上下文和函数的
event
参数)引用对象,因此在函数运行时保持对象活动

一旦
onload
函数返回,图像将变成垃圾(因为它不会在任何地方保存
image
的值)

function loadTexture(gl, url) {
  const texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // Put a single pixel in the texture until it loads
  const level = 0;  const internalFormat = gl.RGBA;  const width = 1;  const height = 1;  const border = 0;  const srcFormat = gl.RGBA;  const srcType = gl.UNSIGNED_BYTE;  const pixel = new Uint8Array([0, 0, 255, 255]);  // opaque blue
  gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,width, height, border, srcFormat, srcType, pixel);

  const image = new Image();

  image.onload = function() {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,srcFormat, srcType, image);

    // WebGL1 has different requirements for power of 2 images vs non power of 2 images so check if the image is a power of 2 in both dimensions.
    if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
       gl.generateMipmap(gl.TEXTURE_2D); // Yes, it's a power of 2. Generate mips.
    } else {
       // No, it's not a power of 2. Turn off mips and set wrapping to clamp to edge
       gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
       gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
       gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    }
  };
  image.src = url;

  return texture;
}

//irrelevant, but including for completeness
function isPowerOf2(value)
{
    return (value & (value - 1)) == 0
}