我有一个简单的函数,导致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>
元素附加到具有更高分辨率版本的图像的'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事件仅发生一次。尽管由于该元素是在之后直接删除的,所以我不明白为什么这会有所不同。
我真的很想知道是否有人可以对此进行阐述,以便我将来可以避免此类问题。干杯。
最佳答案
如果您没有$(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即可满足您的目的。