javascript - 为什么我的 jQuery 函数在 IE 8 中导致 'Stack Overflow' 错误?

标签 javascript jquery

我有一个简单的函数会在 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 resize),宽度/高度在另一个函数中进行比较。

一旦图像增长到一定大小,就会调用此函数,如您所见,它会附加一个隐藏的 <img>。元素添加到具有更高分辨率版本图像的“src”属性的 DOM(如果图像被用户缩小,则更低。

加载后,可见元素的 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() 方法来确保加载事件只发生一次。尽管元素在之后被直接删除,但我不明白为什么这会有什么不同。

我真的很想知道是否有人可以阐明这一点,以便我可以学习如何在将来避免此类问题。干杯。

最佳答案

如果您没有 $(this).remove(),您的初始函数将直接进入无限循环。本质上,您所做的是将 src 属性设置为 all 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 来满足您的目的。

关于javascript - 为什么我的 jQuery 函数在 IE 8 中导致 'Stack Overflow' 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10629013/

相关文章:

javascript - 检测自定义元素上的 onscroll 事件

php - AJAX化网站

jquery - 隐藏所有下一个 tr td 直到下一个 tr th

javascript - 如何将 jquery 代码更改为 javascript 或 typescript

javascript - AMP form select 如何获取data属性的值?

javascript - 访问可变区间

php - 如何使用 Jquery 解析 HTML 以在页面上查找 youtube 或 Vimeo 视频

javascript - rails : 'if running locally' conditional javascript tag include

当用户输入达到一定大小时,Javascript cookie不会保存

javascript - Backbone.js 需要 json2.js?