1

I master the Javascript IIFE essence, but while reading this page, I'm kinda confused of the usage.

It sounds that the following JavaScript pattern is pretty common:

(function(something) {

    something.foo = 123;

})(something || something = {}) 

A usage example:

(function(something) {

    something.foo = 123;

})(something || something = {})

console.log(something); // {foo:123}

(function(something) {

    something.bar = 456;

})(something || something = {})

console.log(something); // {foo:123, bar:456}

As something is defined in the global scope, what is the benefit of this pattern in relation to the following trivial code:

var something;
something.foo = 123;
something.bar = 456; 

Which use case would it make sense to use it?

Mik378
  • 21,881
  • 15
  • 82
  • 180
  • I wouldn't really call it a benefit, but an IIFE destroys the instance after it's run, so perhaps it has a garbage collection advantage over a simple object assignment? – Sterling Archer Jun 10 '16 at 13:10
  • But the variable is defined as global. It would not be trashed even after execution of the IIFE. – Mik378 Jun 10 '16 at 13:11
  • 4
    You seem to have taken the pattern entirely out of context, which makes it hard to point out its benefits (since they only matter with the context). – Quentin Jun 10 '16 at 13:12
  • No, but the function doing the assignments would be destroyed. I guess it really depends on the function scope level. To be honest I find these two methods really incomparable – Sterling Archer Jun 10 '16 at 13:12
  • I don't really see a benefit in this pattern in the way your using it in the examples. You might pass a global varible into the closure (something in your example) as a means to inject global variables into the scope of the closure without directly accessing global itself from within the closure. But your example makes this pretty redundant. Passing something like JQuery makes it more obvious though. You could have multiple Jquery versions, etc. – Liam Jun 10 '16 at 13:12

2 Answers2

2

You get a closure over something which ensured that even though some other code overrides it's in global scope you will still have the right reference to that something, it's better illustrated with jQuery and jQuery.noConflict();:

<script src="/path/to/jquery.js"></script>
<script>
  (function($) {
      // Here $ is jQuery
     // Something asynchrone is happening:
     setTimeout(function() {
       // But $ is still jQuery
     }, 1000); 
  })($);
</script>
<script>
  // Someone calls jQuery.noConflict();
  jQuery.noConflict();
  // And now $ is not jQuery
</script>
Andreas Louv
  • 46,145
  • 13
  • 104
  • 123
  • Yes, this is a better example – Liam Jun 10 '16 at 13:16
  • Actually, I've taken the example of this page: https://basarat.gitbooks.io/typescript/content/docs/project/namespaces.html. I like your example. – Mik378 Jun 10 '16 at 13:17
  • 1
    I'm not convinced by the explanation in that link. It's not a namespace it's a closure. Though a closure can be used *like* a namesepace. Try this [How do JavaScript closures work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) – Liam Jun 10 '16 at 13:21
  • 1
    Actually Typescript compiler generates a closure to deal with namespaces. I don't have a misunderstanding of closures, I struggled to search for a benefit of the pattern. @andlrc makes it far more clearer. – Mik378 Jun 10 '16 at 13:22
-1

Lets say you have a namespace for your application myApp. You have several scripts that add functionality because like a good developer you've broken your application up into different chunks. Also like a good web developer you're loading those scripts asynchronously, you don't know what order they are going to be added in. So you have each module conditionally create the namespace for the app if it doesn't exist (the (myApp || {}) part). You also want to hide the internal functionality of the module from stuff that doesn't need to know about it, so you pass your 'namespace' object into a function that creates a closure and attaches the module's API to the namespace object myApp.

// async loaded script for the foo 'module'
(function(myApp) {
  var myPrivate = 3; // hidden in the closure
  myApp.getFoo = function() { return myPrivate; };
}(myApp || {});

This pattern is not without its flaws (what if myApp.foo depends on myApp.bar?) which is why its largely been replaced by browserify/require.js/webpack/etc.

Jared Smith
  • 19,721
  • 5
  • 45
  • 83
  • this pattern has 100% **not** been replaced by require.js etc. It's pretty much a fundermental part of Js programming – Liam Jun 10 '16 at 13:23
  • @Liam when was the last time you (in production) a) didn't concatenate your files b) didn't use a dependency manager c) if not a && b *manually* set the load order of your scripts tracking which needed to be loaded in order and which were `async`? If you mean closures then yeah sure, people use them all the time (even accidentally). But I'm going to go out on a limb and say that few if any js devs have attached modules to an application this way for the last couple of years. – Jared Smith Jun 10 '16 at 13:34