Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript closure syntax

What is the difference, pros/cons (if any) between these constructs?

 new function(obj) {
     console.log(obj);
 }(extObj);

vs

 (function(obj) {
     console.log(obj);
 })(extObj);
like image 990
vearutop Avatar asked Aug 10 '12 07:08

vearutop


2 Answers

The first one returns a reference to the newly constructed instance of your anonymous constructor function (= this).

The second one returns the return value of the anonymous function. Since your function does not have a return statement, it will implicitly return undefined.

Try the following:

var t1 = new function(obj) { console.log(obj); }(extObj);
var t2 =    (function(obj) { console.log(obj); })(extObj);

typeof t1 => "object"
typeof t2 => "undefined"

(Btw, t1.constructor will return the original function you created t1 with.)

The difference becomes much clearer, if you add a return statement:

var t1 = new function(obj){ return(obj); }("foo");
var t2 =    (function(obj){ return(obj); })("bar");

console.log(t1) => "object"
console.log(t2) => "bar"

IMO, this makes the (function)() much more useful for the everyday usecase - you assign the returnvalue of the execution of this function to the variable which normally would be what you want if you are working with immediately invoked functions. Especially when having more complex things like (pseudocode):

var myNameSpace = (function(){
    /* do some private stuff here*/
    ...
    /* expose parts of your anonymous function by returning them */
    return{
       functionX,
       variable1,
       variable2
    }
}();

Basically you can use an arbitrary unary operator to turn the function declaration into an expression, that is immediately invoked. So you could also write:

!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

depending on the return statement of your function, these will give different return results. ! - negate the returnvalue +|- evaluate as Number (apply negative sign) ~ apply bitwise not to the return value.

like image 186
Christoph Avatar answered Nov 08 '22 06:11

Christoph


If you're looking at dealing expressly with an immediately-invoked function, then there isn't any real difference between the two, except that the first one will return this inside the function, to the outside world, automatically (that is what new does), and by default if a different return value is not specified (regular functions return undefined).

The rest of the major differences are not really going to matter -- access to the prototype chain is going to be pointless, having the returned this.constructor point to the anonymous function would give you access to caching the anonymous function for use at a later time (like removing it from an event listener, if you somehow managed to stick the enclosed function in... ...that would be a trick in and of itself).

Allowing people to cache your immediately-invoked function as a constructor property of the returned this object might be a security-risk... ...or it might be really useful... ...in very specific scenarios.

Every-day purposes of firing code in-line -- no real difference.

like image 22
Norguard Avatar answered Nov 08 '22 06:11

Norguard