有没有办法在 JavaScript/jQuery 中检测递归方法?

3

我正在处理计算代码的一小部分。我需要识别javascript/jQuery中的递归,并终止该递归。

是否有任何API可以支持这个功能在javascript/jQuery中?


@zerkms - 但JavaScript也可以是多线程的(使用Workers)。 - Derek 朕會功夫
@jfriend00 - 它们不共享变量,但它们传递数据,工作线程可以在完成计算器后设置变量的值,而不会停止主脚本。 - Derek 朕會功夫
@jfriend00 - 为什么必须在主脚本执行完成之后才能接受来自worker的消息?我以为JavaScript中的异步脚本是这样工作的:假设有一个无限循环和一个监听器。当监听器从worker接收到一条消息时,循环将被暂停,并且它将开始执行监听器内部的代码。就像一副洗好的牌。 - Derek 朕會功夫
@Derek朕会功夫 - 因为消息是通过事件监听器传递的,而事件仅在主线程未执行时才被处理。在JS引擎内部,当主线程完成执行后,它会查看事件队列以查看是否有需要触发的事件。如果有事件,则立即触发。如果在主线程执行时发生事件,则只需将其放入队列中,直到主线程完成后才会处理。 - jfriend00
@jfriend00 - 好的,我刚刚进行了测试(http://jsfiddle.net/DerekL/h2gKL/),你是完全正确的。我真的以为输出会是`a`和`b`交替出现,但我想我把JavaScript和其他语言混淆了。感谢你教给我新东西。 - Derek 朕會功夫
显示剩余9条评论
2个回答

5
您可以实现自己的递归保护。jQuery 中没有本地支持防止递归的功能。
function myFunc(arg) {
    // if this function already executing and this is recursive call
    // then just return (don't allow recursive call)
    if (myFunc.in) {
        return;
    }

    // set flag that we're in this function
    myFunc.in = true;

    // put your function's code here


    // clear flag that we're in this function
    myFunc.in = false;

}

myFunc.in = false;

你还可以将布尔变量转换为计数器,并仅允许递归到一定层级。值得注意的是,由于JS是单线程的,只有当你的函数从非自己代码的回调处获取数据时,才需要保护它以避免出现问题。如果所有代码都是你自己的,那么你应该确保自己的代码不会引起这种问题。
以下是一个更为严谨的版本,它在闭包中保护了计数器,以免在函数外部被篡改:
 var myFunc = (function() {
     var inCntr = 0;
     return function(args) {
         // protect against recursion
         if (inCntr !== 0) {
             return;
         }
         ++inCntr;

         try {

             // put your function's code here

         } finally {
             --inCntr;
         }

     }
 })();

注意:这里使用了try/finally代码块,因此即使您的代码或您调用的任何代码抛出异常,计数器仍将被清除(因此它永远不会停止)。

1

另一种靠不住的技巧。如果你在递归中使用类似.bind(this)或者使用箭头函数,它将无法工作。

boom();

function boom () {
  if(arguments.callee === arguments.callee.caller) {
    console.log('no recursion will happen');
    return;
  }
  boom();
}

简单的解决方案可能是在参数中设置一个标志。

boom2();

function boom2 (calledRecursively) {
  if(calledRecursively) {
    console.log('no recursion will happen');
    return;
  }
  boom2(true);
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接