【问题标题】:setTimeout() on recursive function within a self invoking functionsetTimeout() 在自调用函数中的递归函数上
【发布时间】:2012-02-07 22:56:49
【问题描述】:

我想将我的代码作为一个自我调用的匿名函数分发,正如我看到的许多人所做的那样。此外,在我的代码中,我必须监视另一个库加载,以便在可用时使用它。

(function(window, document, undefined) {
  staffHappens();
  var initMyLib = function() {
    if (typeof(myLib) == 'undefined') {
      setTimeout("initMyLib()", 50);
    } else {
      useMyLib();
    }
  }
  moreStaffHappens();
  initMyLib(); //-> initMyLib is undefined
})(this, document);

这个错误是怎么发生的? initMyLib 是否应该在封闭(自调用)函数的范围内?

【问题讨论】:

    标签: javascript closures settimeout anonymous-function


    【解决方案1】:

    setTimeout("initMyLib()", 50); 更改为setTimeout(initMyLib, 50);

    当您将字符串作为参数传递时,它会在触发超时时尝试评估它,但它将在全局范围内运行。而且你的方法在全局范围内不存在。


    演示地址 http://jsfiddle.net/gaby/zVr7L/

    【讨论】:

    • @kTash,不应该,但你确定undefined 部分来自该行而不是超时脚本的执行?
    • 我不知道。那是他所说的那一行,所以我认为他已经完成调试以弄清楚那么多...这是我想到的第一件事,但是如果它发生在指定的行而不是超时中,那么我'我不确定这是否正确。我只是在大声思考
    • @ktash,它在我的测试中运行良好......所以我想问题的描述也有错误:)
    • @GabyakaG.Petrioli:嗨。如果我想将参数传递给函数怎么办?如果我这样做,它会给我无限递归。
    • @Dharmraj 那么你需要使用匿名函数。 setTimeout( function(){ initMyLib(params); }, 50);
    【解决方案2】:

    您还可以使用真正的匿名函数来避免范围问题:

    (function() {
        if(typeof(myLib) == 'undefined')
            setTimeout(arguments.callee, 50);
        else
            // loaded
    })()
    

    【讨论】:

    • 一个有效的解决方案,但由于 arguments.callee 在最近的 javascript 版本中已被弃用,你应该避免使用它并使用建议的命名函数。这也可以用 (function name() { 完成,然后使用setTimeout(name, 50);
    • @Gaby aka G. Petrioli:我知道。不过,callee 是一个值得了解的简洁功能。
    【解决方案3】:

    尝试阅读此答案以获取一些线索:recursive function vs setInterval vs setTimeout javascript

    这是来自该答案的代码示例:

    /*
    this will obviously crash... and all recursion is at risk of running out of call stack and breaking your page...
    
    function recursion(c){
        c = c || 0;
        console.log(c++);
        recursion(c);
    }
    recursion();
    
    */
    
    // add a setTimeout to reset the call stack and it will run "forever" without breaking your page!
    // use chrome's heap snapshot tool to prove it to yourself.  :)
    
    function recursion(c){
        setTimeout(function(c){
            c = c || 0;
            console.log(c++);
            recursion(c);
        },0,c);
    }
    
    recursion();
    
    // another approach is to use event handlers, but that ultimately uses more code and more resources
    

    【讨论】:

    猜你喜欢
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 2014-06-04
    • 2020-10-22
    相关资源
    最近更新 更多