2

I was reading a post about how to fire a function after a window resize was complete and came across some examples that assigned self executing anonymous functions to variables:

var delay = (function(){
    var timer = 0;
    return function(callback, ms){
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
})();

$(window).resize(function() {
    delay(function(){
      alert('Resize...');
      //...
    }, 500);
});

What is the difference/benefit of making the function operand self executing as opposed to it's traditional use? i.e.

var delay = function() { ... 
Community
  • 1
  • 1
McShaman
  • 3,627
  • 8
  • 33
  • 46
  • 2
    Creates a new scope :) Only the inner `function`'s code can access the `timer` variable inside. Provides a non-global way to access variables specific only to the function that would normally be outside the main function's scope. – Ian Dec 07 '12 at 08:48
  • @Ian that should be an answer – MrCode Dec 07 '12 at 08:50
  • @MrCode Ehh yet another conflict where someone already posted basically what I have. And I don't have anything to add! I'm sure they do though :) Thanks! – Ian Dec 07 '12 at 08:50
  • 1
    His questions, still remains unanswered. Its not about "what happens", but "why assigning" (translated, "*why creating a function expression instead of using a declaration*) – jAndy Dec 07 '12 at 08:56
  • @jAndy I thought the *why* was answered, no? – deceze Dec 07 '12 at 08:58
  • @deceze: it would also get scoped by a function declaration. – jAndy Dec 07 '12 at 09:07
  • @jAndy Yes, but that would make `timer` part of the `delay` function. Using the above construct `timer` is a variable outside the `delay` function yet not global. – deceze Dec 07 '12 at 09:37
  • @deceze: you're right. I didn't read the code well enough. – jAndy Dec 07 '12 at 10:05

1 Answers1

6

The main reason for this is namespacing variables. Functions introduce a new variable scope. In the case of the above example, timer is not clobbering the global namespace while still being available to the code that needs it.


Since I apparently need to clarify:

The goal is to have a variable outside the function:

var timer;

function delay() {
   // use timer
}

Because if the variable would be inside the function, it would be reinitialized every time. We want a persistent value outside the function though.

In the above code timer is a global variable though. We don't want that. To avoid that, we close the variable up in a new scope so it's accessible to the delay function, but not globally:

var delay = (function () {
    var timer;

    return function () {
        // use timer
    };
})();

delay is now a function just as before which can use timer outside itself, yet timer is not in the global scope.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • So are you saying that if the function was not self executing that `timer` would be in the global name space? Because I just tried: var f = function() { var v = 2; } console.log(v); And I got an error "ReferenceError: Can't find variable: v" – McShaman Dec 07 '12 at 09:06
  • In the above construct, `delay` is the inner returned function, not the self-executing function. Without the anonymous function, the equivalent would be `var timer; function delay(...) { ... }`, which means `timer` is in the global namespace. – deceze Dec 07 '12 at 09:18
  • But Im not talking about the anonymous function. I know it introduces a new variable scope. Im asking about the self executing part. – McShaman Dec 07 '12 at 21:41
  • Check out this little example. Both `bar` variables are not accessible from the global scope. The self execution does not appear to effect the scope. [link]http://jsbin.com/oxikog/6/edit – McShaman Dec 07 '12 at 21:59
  • you don't 'apparently' have to do anything. Also I don't think you are understanding my question. I have updated the jsbin to reflect your example above. I am not talking about pulling the variable timer out of the `delay` function. I am talking about the difference about the entire delay function being self executing or not. [jsbin example](http://jsbin.com/oxikog/7/edit) – McShaman Dec 08 '12 at 00:45
  • @Tim And you apparently don't understand what's going on here. The `delay` function is not self-executing. The function that's going to be the delay function is the inner `function () { // use timer }`, which is being returned from the self-executing anonymous function. That self-executing anonymous function only serves to establish a new scope. The self-executing anonymous function is not assigned to anything, since it self-executes immediately and its *result* is assigned to `delay`. – deceze Dec 08 '12 at 01:16
  • @Tim `var foo = (function () { return 'bar'; })();` The `foo` variable now is the string `'bar'`, not a function. I hope you understand what's happening here now. – deceze Dec 08 '12 at 01:21
  • Ah so the difference between a assigning a self executing function to a variable as opposed to a normal function is that the self executing function will assign the result to the variable where the latter will assign the entire function to the variable? – McShaman Dec 08 '12 at 06:11
  • @Tim Yes, the self executing function is like a one-shot factory method. It works like `var delay = makeDelayFunction();`, just instead of `makeDelayFunction` which is defined elsewhere, you have an inline function expression: `(function () { ... })`. That function expression is not assigned to anything and has no name and is executed immediately, so only its result will stay, not the function itself. – deceze Dec 08 '12 at 09:12