为什么js图像对象没有被垃圾回收?
Why isn't the js image object garbage collected?
我有 C++ 背景并正在学习 javascript。 webgl 上的 Mozilla 教程具有类似于下面的代码(实际代码和底部的 link)。我试图理解为什么 "onload" 回调函数中的代码总是会被执行。在我看来,Image 对象实例应该在下面的代码中被垃圾收集。所以理论上它可以在加载完成并调用 "onload" 回调之前被垃圾收集。
function foo()
{
image = new Image();
image.onload = function()
{
/*stuff to do when image gets done loading */
Console.log(image.width);
}
image.src = url;
}
我唯一的想法是使用 "image.width" 的函数——函数对象必须将图像实例保存在内存中。但这将是一个循环引用,因为该功能仅存在于图像对象本身上;函数对象的唯一引用 AFAIK 是它的 onload 回调 属性。所以循环引用(image->onload->function->image->...)应该被垃圾回收。
我好像有点不明白,或者图片加载和垃圾回收之间存在竞争条件。
JS 引用显示循环引用岛不再可达,应该进行垃圾回收。 https://javascript.info/garbage-collection
教程Link:
https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
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
}
当您分配给 image.src
时,Image
对象将添加到浏览器的内部队列中,以供异步加载的所有外部对象使用。这个队列防止对象在函数 returns 时立即变成垃圾。队列只是浏览器管理加载这些对象的过程所必需的——它需要保存正在加载的对象,因此它知道在从服务器获得响应时要做什么。
加载图像时,其 onload
函数被添加到事件队列中,并且由于它通过 image
变量(以及 this
函数的上下文,以及函数的 Event
参数),在函数 运行.
时保持对象存活
一旦 onload
函数 returns,图像将变成垃圾(因为它不会在任何地方保存 image
的值)。
我有 C++ 背景并正在学习 javascript。 webgl 上的 Mozilla 教程具有类似于下面的代码(实际代码和底部的 link)。我试图理解为什么 "onload" 回调函数中的代码总是会被执行。在我看来,Image 对象实例应该在下面的代码中被垃圾收集。所以理论上它可以在加载完成并调用 "onload" 回调之前被垃圾收集。
function foo()
{
image = new Image();
image.onload = function()
{
/*stuff to do when image gets done loading */
Console.log(image.width);
}
image.src = url;
}
我唯一的想法是使用 "image.width" 的函数——函数对象必须将图像实例保存在内存中。但这将是一个循环引用,因为该功能仅存在于图像对象本身上;函数对象的唯一引用 AFAIK 是它的 onload 回调 属性。所以循环引用(image->onload->function->image->...)应该被垃圾回收。
我好像有点不明白,或者图片加载和垃圾回收之间存在竞争条件。
JS 引用显示循环引用岛不再可达,应该进行垃圾回收。 https://javascript.info/garbage-collection
教程Link: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
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
}
当您分配给 image.src
时,Image
对象将添加到浏览器的内部队列中,以供异步加载的所有外部对象使用。这个队列防止对象在函数 returns 时立即变成垃圾。队列只是浏览器管理加载这些对象的过程所必需的——它需要保存正在加载的对象,因此它知道在从服务器获得响应时要做什么。
加载图像时,其 onload
函数被添加到事件队列中,并且由于它通过 image
变量(以及 this
函数的上下文,以及函数的 Event
参数),在函数 运行.
一旦 onload
函数 returns,图像将变成垃圾(因为它不会在任何地方保存 image
的值)。