2

i wonder what the difference is between these two declarations:

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


function delay {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
}
Justin Johnson
  • 29,495
  • 7
  • 60
  • 86
ajsie
  • 70,516
  • 97
  • 259
  • 375

5 Answers5

3

The first function declaration uses an anonymous function to create a closure over the variable timer and a second anonymous function to avoid polluting the global namespace with timer. This is a simple and handy technique to implement data hiding and static variables within a function in JavaScript.

This first/outer function typically only gets used once, which is why it is never given a name, but instead is executed immediately as an anonymous function. However, the opposite is true if you needed to be able to create multiple timers for multiple events.

Consider the following:

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

Now:

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

is equivalent to:

var delay = delayBuilder();

So, if you needed to have multiple delays (more than one timer running at the same time), you could do:

var delay1 = delayBuilder(), delay2 = delayBuilder(), ... delayN = delayBuilder();

// And of course, used as:
delay1(callback, ms);

More generalized, you have a function to build functions, in other words funcBuilder and func (using "func" since "function" is a reserved word).

var func = funcBuilder(configurationifany);

So, if the function builder was more complex and you wanted a single, throw-away instance of whatever function it was building, you could do

funcBuilder(configurationifany)(etc, etc);

Or in the case of the code that you posted (although this is overkill for simply wrapping setTimeout but just to continue the example):

delayBuilder()(callback, ms);

It really boils down to usage. If you're not going to use the function builder more than once, there's no sense in keeping it around and executing it as an anonymous function is more appropriate. If you need to build multiple instances of that function, then saving a reference to the function builder makes sense.

Justin Johnson
  • 29,495
  • 7
  • 60
  • 86
1

In the second case you discard the returned function.

If I understand your question right, that is if you want the second case to be

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

then the difference is that the code stored into delay is not executed. If you call delay later, then it will be equivalent and the difference would be anonymity of the function and the value of delay (in the first case it's inner function, in the second - outer one).

Michael Krelin - hacker
  • 122,635
  • 21
  • 184
  • 169
  • 1
    But if it were `function delay() { ... }` then the difference would be that in the first case delay is assigned the *inner* function, i.e. the return value of outer one. And in the second case it will be the outer function. In the first case it is called, in the second case it is not. – Michael Krelin - hacker Dec 19 '09 at 12:41
  • In the second case the code is not executed, so it can't return anything. – Guffa Dec 19 '09 at 12:42
  • Guffa, it *can* once it's called ;-) I mean, it's stored in the variable, so nothing prevents one from calling it later. – Michael Krelin - hacker Dec 19 '09 at 12:44
1

The purpose of having a function return another function is to create a scope for variables declared outside the function without having to declare them globally. The outer function is executed immediately after it's created (by putting the parentheses after the declaration), so the inner function is returned and assigned to the variable.

In the first example the timer variable is used in the inner function, so a closure is created that contains the variable. When you later use the function, it still has access to the timer variable although it's not inside the function itself. The outer function is executed so that it returns the inner function, and it's assigned to the delay variable.

Discussing the difference between the two declarations is pointless. The second declaration only declares the outer function, but then it's neither stored nor executed so it's just thrown away.

Edit:
In your updated question (if corrected by adding parentheses efter the function name in the second declaration), the second declaration is a function that returns the same result that is assigned to the variable in the first declaration. So to get the same result you have to call the function and assign the return value to a variable:

var d = delay();

Now the d variable contains the same as the delay variable in the first example.

Guffa
  • 640,220
  • 96
  • 678
  • 956
0

The first case uses a function expression to generate an anonymous function, which is called instantly and which wraps a timer variable in a closure and returns another function (generated with a function expression).

The second case is a syntax error (since there is no context for a function expression and no name for a function declaration).

Since you have now edited it…

The second case now uses a function declaration, but doesn't call the function. So it will now do what the anonymous function does (and not what the returned function does).

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
0

In the first case, you create then call an anonymous function. In the second, you create an anonymous function but neither call it nor save it in a variable. I'm not even sure that's legal.

outis
  • 68,704
  • 19
  • 132
  • 197