我有一个简单的函数,它会在IE 8中导致堆栈溢出错误。虽然我没有测试IE 7或6,但是在任何其他浏览器中似乎都没有出现这个问题。
确切的错误如下: -
SCRIPT28: Out of stack space
jquery.min.js, line 2 character 7498
SCRIPT2343: Stack overflow at line: 2
有问题的功能:
function switchImage(size, objid, prefix, fullimage){
if(size !== 'full'){
var image = prefix + size + '/' + size +'_' + fullimage;
}
else {
var image = prefix + size + '/' + fullimage;
}
$('#' + objid).data('type', size)
.append('<img id="preload" src="' + image + '" style="display:none;" />')
.find('#preload').load(function(){
$('#' + objid).find('img').attr('src', image);
$(this).remove();
});
}
为了概述用例,我将解释这个功能的用途:
当用户调整图像大小时(使用jqueryUI调整大小),将在另一个函数中比较宽度/高度。
一旦图像增长到一定大小,然后调用此函数,如您所见,将隐藏的<img>
元素附加到DOM,并使用更高分辨率版本的图像的'src'属性(如果用户缩小图像尺寸,则降低。
加载后,可更新可见元素的src属性,并删除隐藏元素。
这证明了图像的优异动态切换,因为用户调整了图像的大小,在整个过程中保持图像质量良好....
我似乎无法解决IE 8中导致问题的原因。删除此功能不会发生错误,虽然存在错误,但功能仍然可以正常工作(尽管调整大小的性能仍然很差)在IE 8)。
非常感谢任何帮助。
更新:我似乎通过将函数重写为以下内容来解决原始问题: -
function switchImage(size, objid, prefix, fullimage){
var $el = $('#' + objid);
if(size !== 'full'){
var image = prefix + size + '/' + size +'_' + fullimage;
}
else {
var image = prefix + size + '/' + fullimage;
}
$el.data('type', size);
$('<img id="preload" src="' + image + '" style="display:none;" />')
.appendTo($el)
.one('load', function(){
$('#' + objid).find('img').attr('src', image);
$(this).remove();
});
}
正如您所看到的,唯一真正的区别是我使用.appendTo()而不是.append()以及使用jQuery .one()方法来确保load事件只发生一次。虽然之后直接删除了元素,但我不明白为什么这会产生任何影响。
我真的很想知道是否有人可以对此有所了解,以便我可以学习如何在将来避免这些问题。欢呼声。
答案 0 :(得分:3)
如果您没有$(this).remove()
,那么您的初始函数将直接进入无限循环。基本上您正在做的是将src
属性设置为所有 img
标记,包括预加载图像本身。 (将$(this).remove()
替换为console.log('loaded')
并观察它在Firebug中无限循环播放)
我猜想在IE8中,一旦属性设置为预加载图像,它会先执行$(this).remove()
(解释堆栈溢出),而其他浏览器可能首先完成了整个函数的执行,从而删除了预加载图像,这阻止了无限循环。 (这只是猜测)
初始版本的猴子补丁将使用.find('img:not(#preload)')
而不是.find('img')
。
您的补丁也会阻止无限循环,因为.one()
确保它只运行一次。
但最终我会将该函数重构为以下内容:
function switchImage(size, objid, prefix, fullimage){
var $el = $('#' + objid),
$image = $el.find('img'),
$preload = $('<img>');
if(size !== 'full'){
var image = prefix + size + '/' + size +'_' + fullimage;
}
else {
var image = prefix + size + '/' + fullimage;
}
$el.data('type', size);
$preload
.on('load', function () {
$image.attr('src', image);
})
.attr('src', image);
}
另请注意,预加载图像实际上不需要显式附加到DOM以满足您的目的。