0

Here's a code

(function(x){
    // Some code here
})(1);

The code above is IIFE so this means that it will be executed just once. Qustion: why would anybody need to pass parameter into this function (whick is 1 in example below)?

I can just create variable inside function, like below

(function(){
    var x = 1;
    // Some code here
})();

This question is not about how closures work but about why and when to use first code pattern and when the second one.

Alex Velickiy
  • 541
  • 1
  • 7
  • 22
  • Please take a look at [javascript-closure-inside-loops-simple-practical-example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example). Bjorn Tipling's answer contains "an useful IIFE" with a passed parameter. – Teemu Feb 14 '15 at 17:46
  • The obvious reason is because they want to be able to vary the value of x. – James Feb 14 '15 at 18:13
  • You're totally right. The only case where this construct is required would be when you want to pass a variable value and the identifier would be shadowed by something local in the function. – Bergi Feb 14 '15 at 18:38
  • @Andreas well, it's obviously not. This question is not about how closures work but about why and when to use first code example and when the second. – Alex Velickiy Feb 15 '15 at 11:45
  • @Teemu thanks for reply. Just looked at example you referenced and want to say that the same effect can be got without using parameter and with using local variable. So both variants can be used.var fs = []; var i, j; for (i=0; i < 3; i++) { fs.push((function () { var k = i; return function() { console.log(k); } })()); } – Alex Velickiy Feb 15 '15 at 11:48
  • @Bergi Could you please explain what you mean in more details. – Alex Velickiy Feb 15 '15 at 11:50
  • @James Could you please explain what you mean in more details. – Alex Velickiy Feb 15 '15 at 11:51
  • @Tigrokonvel The linked question supplies many examples of **when** to use a closure and **why** – Andreas Feb 15 '15 at 12:02
  • @Teemu Disagree. Just try to run example that I provided in previous comment to you. – Alex Velickiy Feb 15 '15 at 12:06
  • @Andreas But my question is about **when** and **why** to use IIFE pattern #1 and IIFE pattern #2 – Alex Velickiy Feb 15 '15 at 12:08
  • @Tigrokonvel: See the example in the answer by Ingo Bürk – Bergi Feb 15 '15 at 13:22

3 Answers3

4

For one, it can be considered a matter of style. I would prefer

(function (x, y, z) { … })(1, 2, 3);

over

(function () { var x = 1; var y = 2; var z = 3; … })();

if x, y and z are what I would usually pass as a parameter rather than a local variable (so where I declare it depends on what information they hold).

But, in the case of jQuery and other code, what you can essentially do is alias certain names:

(function (window, undefined) {
    // …
})(window);

This snippet does two things:

  • It renamed the global window to a local window. When writing the code, this has absolutely no effect. But when the code is minified, the minifier can rename the IIFE's argument to w – and all usages of it within the function. This way, window only has to be written out one single time, which can potentially save quite a bit of bytes.
  • It declares the parameter undefined, but doesn't pass anything to it. This causes the parameter named undefined to hold the value undefined. It isn't so important anymore these days, but older browsers allow redefining the value of undefined and by doing this, you can make sure no other code will interfere with yours by overwriting the value (which, of course, is a terrible thing to do).
Ingo Bürk
  • 19,263
  • 6
  • 66
  • 100
  • On the second note, I would not code based on old, decrepit coding conventions as it leads to developer confusion. We don't check to make sure someone didn't turn `Array` into a duck. As you said, newer browsers define it as a keyword. Either way, check undefined with `thing == null` (double-equals, not triple), or `'propertyName' in thing`. That's my convention, as any extra bits on my code that a newbie can't figure out reduce readability. – Katana314 Feb 14 '15 at 18:39
  • @Katana314 I think using `thing == null` to check for `undefined` is worse as a) no newbie will get that it's a check for `undefined` and b) it has the side effect of checking for `null` as well. Never mind that you duplicate this all over the place. The `undefined` parameter is a one time thing and you're done with it. If you don't want to deal with this, just don't do it at all and assume `undefined` has not been redefined. – Ingo Bürk Feb 14 '15 at 19:23
  • But you have to replicate the undefined thing in every file; of which organized code should have several to differentiate functionality. Generally, I want to find null as well as undefined; it's not very frequent that the difference between the two will help any programmers at all. – Katana314 Feb 15 '15 at 00:27
  • Thanks for reply. It's first time I hear about undefined redefining problem - interesting. About aliasing: the same effect can be got if I use local variable (var w = window;). Or the idea here to keep using window variable (not something else) inside funtion? – Alex Velickiy Feb 15 '15 at 12:01
  • @Tigrokonvel Yes, by using a parameter you can keep writing `window` which makes it much easier to understand. It also separates the concern of allowing minification from actually writing the code itself. It's an alias, but with the same name. – Ingo Bürk Feb 15 '15 at 12:03
1

The most probable use case is of jQuery.

(function($) {
    console.log($);
})(jQuery);

This way no matter what other libraries like Prototype or Mootools you load, your code is always safe inside an IIFE. You can also pass other libraries like Prototype and Mootools using this pattern.

(function($, P, Moo) {
    console.log($);
    console.log(P);
    console.log(Moo);
})(jQuery, $, $$);

Hope this helps!

Piyush Chauhan
  • 1,523
  • 2
  • 24
  • 37
0

Consider the difference in the behaviors of these two event handlers:

var tags = document.getElementsByTagName("a");
for (var i=0, t; t = tags[i]; i++) {
  t.addEventListener("click",
    (function (index) { 
      return function () { 
        console.log("iife - " + index); 
      };
    })(i)
  );
  t.addEventListener("click",
    function () { 
      var index = i;
      console.log("non iife - " + index); 
    }
  );    
}

demo

James
  • 20,957
  • 5
  • 26
  • 41
  • Thanks for reply. But the same effect can be got if I use local variable: t.addEventListener("click", (function () { var index = i; return function () { console.log("iife - " + index); }; })() ); – Alex Velickiy Feb 15 '15 at 12:04