6

I want to distribute my code as a self-envoking anonymous functions, as I see many do. Also, within my code I have to monitor for another lib loading, so I can use it when it's available.

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

How can this error occur? Should initMyLib be inside the scope of the enclosing (self-envoking) function?

user967722
  • 1,213
  • 1
  • 20
  • 26

3 Answers3

12

change setTimeout("initMyLib()", 50); to setTimeout(initMyLib, 50);

When you pass a string as an argument it will try to evaluate it when the timeout is fired, but it will run in the global scope. And your method does not exist in the global scope.


Demo at http://jsfiddle.net/gaby/zVr7L/

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
  • @kTash, not it should not, but are you sure the `undefined` part comes from that line and not an execution of the timeout script ? – Gabriele Petrioli Jan 11 '12 at 15:27
  • I don't know. That is the line he has stated it occurs so I'm figuring he's done debugging to figure that much out... This was the first thing I thought, but if it is occurring at the line specified and not in the timeout, then I'm not sure this is right. I was merely thinking aloud – LoveAndCoding Jan 11 '12 at 15:30
  • @ktash, well it works fine in my tests ... so i guess there is an error in the description of the problem as well :) – Gabriele Petrioli Jan 11 '12 at 15:32
  • @GabyakaG.Petrioli : Hie. What if I want to pass the arguments to function ? If I do so , It gives me infinite recursion. – Dharmraj Sep 22 '14 at 06:06
  • @Dharmraj then you need to use an anonymous function. `setTimeout( function(){ initMyLib(params); }, 50);` – Gabriele Petrioli Sep 22 '14 at 06:16
  • @GabyakaG.Petrioli : Worked perfect. Thanks for helping me quickly :) – Dharmraj Sep 22 '14 at 06:34
2

Try reading this answer for some clues: recursive function vs setInterval vs setTimeout javascript

This is the code sample from that answer:

/*
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
Community
  • 1
  • 1
adeler
  • 151
  • 1
  • 5
  • The second part of the response is incorrect. Timeout does not reset the call stack, although that fact is rarely known. I tested this on both Chrome and Safari - same results - infinite stack growth. See https://medium.com/@devinmpierce/recursive-settimeout-8eb953b02b98 – John Moore Feb 26 '21 at 23:17
2

You could also use a real anonymous function to avoid scoping issues:

(function() {
    if(typeof(myLib) == 'undefined')
        setTimeout(arguments.callee, 50);
    else
        // loaded
})()
georg
  • 211,518
  • 52
  • 313
  • 390
  • 2
    A valid solution but since `arguments.callee` is deprecated in recent javascript versions, you should avoid using it and use the suggested one which is named functions.. This could be also done with `(function name() {` and then use `setTimeout(name, 50);` – Gabriele Petrioli Jan 11 '12 at 15:47
  • @Gaby aka G. Petrioli: I know. Still, `callee` is a neat feature worth knowing about. – georg Jan 11 '12 at 17:16