13

(function(){ ... })();

I HAVE looked at this post and understood a bit about it. But there are few more doubts, mostly on how it is used.


Like a Static block!

since it acts like a static block (self invoking!), it can be used for initializing(like some make-believe constants)?

But then there is no getter available to fetch anything from it and use it elsewhere!


return, Must?

The solution to above is to HAVE a return in that function? so that I can fetch whatever it returns and use that.


reference to the global object?!

(function(window, undefined){})(this);

The explanation for the above code was in the second answer of the referenced post, I couldn't understand it, If anyone can explain it more (or simpler for me), It will be great


update: Take a look at this code ↓

var myElement=document.getElemetById("myElementId");
 (function(myElement){
      /**'this' here is 'myelement'???**/
 }; 
})(this);
Community
  • 1
  • 1
  • 1
    *"can be used for initializing"* Initializing of what? *"The solution to above is to HAVE a `return`?"* What? *"reference to the global object?!"* Inside the global scope, `this` refers to the global object. – Felix Kling Aug 13 '13 at 08:23
  • Its used a lot for protecting scope, thus keeping the global environment clean & avoiding namespace clashes. – Alex Aug 13 '13 at 08:32
  • @FelixKling initializing variables, constants... Like that!having a `return` statement will allow me to fetch something from that functio? –  Aug 13 '13 at 08:48
  • on a side note, don't forget to tuck in the 'dog balls': (function(){}()) – zclark Aug 13 '13 at 11:27

3 Answers3

15

A common metod is the following (called namespacing) - It created an encapsulated scope by immediately executing your function and returning the essential parts you need into your variable:

var yourNamespace = (function(window, undefined){ 
                    /* private code:*/
                    var privateVar = "foobar",
                        count = 0;
                    /* the stuff you want to use outside: */
                    return{
                       val: 5,
                       publicVar:privateVar,
                       func:function(){return ++count}
                    }
             })(this);// `this` is a reference to `window` here

This way you have access to everything you need via your yourNamespace variable, while still maintaining privacy and not polluting the global object. It's called namespacing and uses the closure paradigm. You can also hand over functions to work with private (for the enclosing scope non-visible) variables.

One reason for handing over undefined was, that in ES3 undefined was writable, which it is not the case anymore in ES5. Handing over over this as parameter shortens the lookup by creating a direct reference to the global window object in the scope. However, be very cautious - in ES5 strict mode this is not the window anymore but resolves to undefined!! So this is not recommended anymore!

Another reason for handing over window and undefined is that now that these are variable names, a minifier could compress them to a single letter.

if(myVar == undefined)
// could be compressed to:
if(a==x)

EDIT to your question:

The this will not change in your example, you need one of the following solutions:

(function(myElement){/*your code*/})( document.getElemetById("myElementId") );
// or:
(function(){
    var myElement = document.getElemetById("myElementId");
    /* your code */ 
})();
Christoph
  • 50,121
  • 21
  • 99
  • 128
  • so if I write `this.something` **inside that function** it means `window.something`? and in your example it is not necessary to mention `window` right? since on it is not being used, or am I missing something? –  Aug 13 '13 at 08:56
  • with the exception of the ES5 strict mode - yes. However, `this` could not be minified as it is a keyword, while writing `window.something` could be. When you have don't need a reference to `window`, you can of course omit that parameter. – Christoph Aug 13 '13 at 09:01
  • @rps the value of `this` is not actually affected by the pattern here. The argument named `window` is passed the value of `this` when the function executes, which in this case is a reference to `window`. `this` is a keyword which in some circumstances would also refer to `window` in your example. – robC Aug 13 '13 at 09:19
  • @rps to summarize robC's (for me) confusing comment: The keyword `this` always refers to the "owner" of the function you're executing ( - the object the function is a method of). In the case of an immediately invoked function expression, it always refers to `window` or in ES5 strict mode to `undefined`. – Christoph Aug 13 '13 at 09:41
  • @Christoph IF I pass something other than `window` to that function, will it still work the same? (say if I wanna fetch the value of a hidden element which is dynamically created and keep it private, so I pass the ref to that to the self-invoking function) –  Aug 13 '13 at 09:50
  • @rps you don't pass window, you pass the this keyword, which in the IIFE context refers to the window object. You don't need the window reference if you actually don't want to use window in your IIFE. But I don't understand your whole intention. Can you perhaps edit your question or open a new one explaining this problem further? – Christoph Aug 13 '13 at 10:07
  • @rps updated my answer. Don't get confused by the parametername, it doesn't matter - what matters is the argument you pass to the function. – Christoph Aug 13 '13 at 11:18
2

The main point of an iife is to create an encapsulated scope. Otherwise, all the variables that you declare will end up in the global scope.
If you need to make something accessible from within that scope you can explicitly create a global namespace variable i.e. window.myApp = {} and attach it there i.e. window.myApp.myMethod = function(){...}
The reason for passing window into the iife is that it creates a local reference within the scope. That will shorten the lookup chain for better performance and the variable will also be minifiable.


In answer to your updated question:

To create a local ref to an element using this pattern you would supply it to the iife as an argument:

(function(element){

    element.style.top = "100px";

})(document.getElementById("myId"));

...but i'm not sure that there is much value to using the pattern in this way? As per my comment, the this keyword is not affected and will still point to window in this example.

I think that the this keyword is confusing you - it is not necessarily relevant to the iife pattern. Here is a good explanation of how its value is determined: http://net.tutsplus.com/tutorials/javascript-ajax/fully-understanding-the-this-keyword/

robC
  • 2,592
  • 1
  • 23
  • 28
  • 1
    more than `this`, `function(window)` was confusing! coz I thought that that is what identifying the function's _owner_, I thought the _owner_ can be changed like a normal function's using `function(somethingelse)` (not the same syntax for normal functions!), but yea now understood it fully, thanks –  Aug 13 '13 at 11:18
2

> it can be used for initializing? ... there is no getter available to fetch anything from it!

yes it is often used for initialization and there is no need to fetch anything though it might.

> The solution to above is to HAVE a return?

no, it have not to have a return but again it might. If there is a return it will be past to whatever... i.e.

var a = (function(){})();

a will have whatever returned or undefined.

(function(window, undefined){})(this);

parameter this will be the invoker - usually it is window , but might be any object. if you pass this as a parameter it will be accessible through the 1st argument ( window in the case).

Hope the explanations are clear enough.

vsync
  • 118,978
  • 58
  • 307
  • 400
i100
  • 4,529
  • 1
  • 22
  • 20