如何在Javascript中增加最大调用堆栈?

She*_*zod 10 javascript jquery dom javascript-events

我有一个可以解雇的事件.我尝试使代码尽可能高效,但在某些情况下它可以达到最大调用堆栈,这是我无法控制的.它不是一个无限的堆栈,它会在某个时刻结束,但有时它可能会因为极限而在它完成之前崩溃.

如果我设置2个类似的事件监听器并拆分代码,我会增加调用堆栈的数量吗?或者我该怎么办?

更新:它是关于DOM更改事件(仅使用Webkit,因此不关心其他浏览器),它也可以根据某些条件修改DOM.我还没有真正达到这个限制,但从理论上说,它可能会.我仍在优化代码,以尽可能减少DOM操作.

更新2:我包括示例(非真实)示例:

document.addEventListener('DOMSubtreeModified', function(event){

    this.applyPolicy(event);

}, true);

function applyPolicy(event){
    if( typeof event != "undefined" ){
        event.stopPropagation();
        event.stopImmediatePropagation();
    }

    if( !isButtonAllowed ){
        $('button:not(:disabled)').each(function(){

           $(this).attr('disabled', true);

        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这只是一个示例代码,但即使在这种情况下,如果您说100个按钮,调用堆栈也将在100秒内.请注意,如果使用$('button').attr('disabled', true);,这将导致调用堆栈问题,因为jQuery将尝试无限地修改DOM.

Eve*_*ert 6

对于任何浏览器,最大调用堆栈运行数千.你应该尝试优化代码,拥有一个巨大的调用堆栈对速度和内存不利.

如果您遇到此问题,则表明您的代码迫切需要重组

  • 如果它真的是你正在处理的第三者,那么我同意你的看法......这可能是处理此类事情的唯一方法。在这种情况下,我会尝试确保您的事件不能递归触发。当您的第一个 DOM 更改事件触发时,您可以暂时禁用此事件,并且仅在*完成此事件后*再次打开它。这将使堆栈不可能失控。PS:我喜欢在 stackoverflow 上谈论堆栈溢出问题;) (2认同)

小智 6

虽然听起来你可能需要重新考虑一些代码,但有一种可能性是setTimeout在某个给定的时间间隔内进行递归调用.这允许您开始新的调用堆栈.

以这个例子为例......

var i = 0;

function start() {
    ++i;
    var is_thousand = !(i % 1000);

    if (is_thousand)
        console.log(i);

    if (i >= 100000)
        return; // safety halt at 100,000
    else
        start()
}
Run Code Online (Sandbox Code Playgroud)

它只是每隔一段时间记录到控制台1,000.在Chrome中,它超出了30,000范围内的堆栈.

演示: http : //jsfiddle.net/X44rk/


但如果你像这样重做......

var i = 0;

function start() {
    ++i;
    var is_thousand = !(i % 1000);

    if (is_thousand)
        console.log(i);

    if (i >= 100000) // safety halt at 100,000
        return;
    else if (is_thousand)
        setTimeout(start, 0);
    else
        start();
}
Run Code Online (Sandbox Code Playgroud)

现在,每个1,000函数都将被允许返回,下一次调用将异步进行,启动一个新的调用堆栈.

请注意,这假定在进行递归调用时函数有效结束.

还要注意我有条件停下来100,000所以我们不是无限的.

演示: http : //jsfiddle.net/X44rk/1/