tags:

views:

124

answers:

2

Hi,

I've made this code:

window.setInterval(function(){ var a = doStuff(); var b = a + 5; }, 60000)

The actual contents of the anonymous function is of course just for this small example as it doesn't matter. What really happens is a bunch of variables get created in the scope of the function itself, because I don't need/want to pollute the global space.

But as you all know, the doStuff() function won't be called until 60 seconds in the page. I would also like to call the function right now, as soon as the page is loaded, and from then on every 60 seconds too.

Is it somehow possible to call the function without copy/pasting the inside code to right after the setInterval() line? As I said, I don't want to pollute the global space with useless variables that aren't needed outside the function.

+5  A: 

You can put your callback function in a variable, and wrap up everything in a self-invoking anonymous function:

(function () {
    var callback = function() { 
        var a = doStuff(); 
        var b = a + 5; 
    };

    callback();

    window.setInterval(callback, 60000);
})();

No pollution.

Daniel Vassallo
+1 while the below code is totally valid, I consider it to be annoying to read.
ItzWarty
Cool, this works nicely!
Tominator
+2  A: 

This is possible without creating global variables as well:

setInterval((function fn() {
 console.log('foo'); // Your code goes here
 return fn;
})(), 5000);

Actually, this way, you don’t create any variables at all.

However, in Internet Explorer, the fn function will become accessible from the surrounding scope (due to a bug). If you don’t want that to happen, simply wrap everything in a self-invoking anonymous function:

(function() {
 setInterval((function fn() {
  console.log('foo'); // Your code goes here
  return fn;
 })(), 5000);
})();

Credit to Paul Irish for sharing this trick.


Edit: Answer updated with some more information, thanks to bobince.

Mathias Bynens
Clever! Almost too clever :)
Miles
hmm in this case the anonymous function gets called once, but then the setInterval function says "invalid argument passed". It's probably getting the result of the executed function and tries to re-execute that (which is void) after 5 seconds.
Tominator
@Tominator: That shouldn’t happen. The code snippet I posted works fine in my console. Please show us your code.
Mathias Bynens
-1 nope this doesn't conform to the requirement. It creates `fn` in the global space. Thats the problem with clever tricks, its hard to predict what they are actually doing.
AnthonyWJones
@AnthonyWJones and @ItzWarty: Easy enough to fix — just wrap the whole in a self-invoking anonymous function. I edited my answer. @AnthonyWJones: IIRC, the requirement was to avoid global variables, not functions.
Mathias Bynens
Actually, Anthony can be right or wrong. It matters, what scope is the code put into? If the code is put into a window.onload, it's not global, it's a private function inside window.onload... @Mathias Bynens: While the code is clever, it's not exactly legible. I will +1 for the cleverness, though.
ItzWarty
Ack. My sillyness. I skipped the contents of your fn() function mentally, so I failed to notice you returned the function itself. Of course that works then :-)And i don't know if it creates the function in global space. Closures are hard, my head fails at them.
Tominator
Also, a global function == a global variable, as var a = function(){} is the same as function a(){}, apparently. I should have been more clear that indeed a global function is also what I would like to avoid. Thanks for the discussion and the idea!
Tominator
@Tominator: See ItzWarty’s comment. Using my first code sample, the function may or may not become global — it depends. Using the second one, it will never be global.
Mathias Bynens
It shouldn't create the function in the surrounding scope even without the wrapper. It's only in IE that it does, due to a long-standing JScript bug. What's more, in IE only, the returned `fn` is not actually the same function instance as the one being called to return it! For these reasons, named inline function expressions should normally be avoided.
bobince
The code will be added by asp.net as a script-block somewhere in the body tag on the page. It'll execute because the browser happens to read the code (poor man's window.onload). I wish i could mark both answers as valid now :-)
Tominator
@bobince Thanks for the additional info! I slightly updated my answer.
Mathias Bynens