Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference in the following JS syntax?

Tags:

javascript

Following are two ways to define BW.Timer. Can someone tell me what the difference is? I am not certain the first is even valid, but if it is valid, what is different about using the myfunc=(function(){}()) syntax?

BW.Timer = (function () {
    return {
        Add: function (o) {
            alert(o);
        },
        Remove: function (o) {
            alert(o);
        }
    };
} ());

And...

BW.Timer = function () {
    return {
        Add: function (o) {
            alert(o);
        },
        Remove: function (o) {
            alert(o);
        }
    };
};
like image 238
John Livermore Avatar asked Dec 04 '12 19:12

John Livermore


2 Answers

The first is the return-value of the immediately-invoked function. The second is a function. It essentially comes down to what the difference is between these:

var f = (function() { return 0; })();

var f = function() { return 0; };

Since the first function is called immediately, the value of 0 is given to the variable f. The first f is not a function. However, the second f we must call in order to get the value:

f(); // 0

It follows that in your example, the first BW.Timer is the object literal itself and the second is a function returning an object literal. You must call the function in order to get to the object:

BW.Timer().Add(x);

Why use the first then?

You might ask yourself why one would use a syntax like a = (function() { return {}; })() instead of a = {}, but there's a good reason. An IIFE (Immeditately-Invoked Function Expression), unlike a regular function allows the emulation of static variables (variables that maintain their value through a single instance). For example:

var module = (function() {
    var x = 0;

    return {   get: function()  { return x },
               set: function(n) { x = n }
    };

})();

The above a text-book example of the Module Pattern. Since the function is called right away, the variable x is instantiated and the return value (the object) is given to module. There's no way we can get to x other than by using the get and set methods provided for us. Therefore, x is static, meaning its variable won't be overridden each time you use module.

module.set(5);

module.get(); // 5

On the other hand, let's see an example where module is declared as a function instead:

// assume module was made as a function

module().set(5);

module().get(); // 0

When we call module() the x variable is overridden each time. So we're effectively using different instances of module and x each time we call module.

like image 71
David G Avatar answered Oct 03 '22 02:10

David G


The difference is rather large.

In the first case, BW.Timer is executed when it is first encountered, and that is the static version assigned to BW.Timer. In that instance, BW.Timer.Add(1) may be used. Each call to BW.Timer will be the same object.

In the second case, BW.Timer is not executed when first encountered, and instead is a function referece which must be invoked BW.Timer(). For Add to be used, this must be the case BW.Timer().Add(1). Also, you can issue var timer = new BM.Timer();. Each instance of BW.Timer() will be unique here.

like image 32
Travis J Avatar answered Oct 03 '22 03:10

Travis J