Difference between an IIFE and non-IIFE in JavaScript Modular approach
Asked Answered
C

2

8

Recently while I was trying to learn more about IIFE and modules in JavaScript a question came to my mind that how is IIFE making a Module while not Immediately Invoking the function doesn't make it a module..

can anyone share with me the Difference between this code

var MODULE = (function () {
var my = {},
    privateVariable = 1;

function privateMethod() {
    // ...
}

my.moduleProperty = 1;
my.moduleMethod = function () {
    // ...
};

return my;
}());

and this code where the function is not Immediately Invoked..

var MODULE = function () {
var my = {},
    privateVariable = 1;

function privateMethod() {
    // ...
}

my.moduleProperty = 1;
my.moduleMethod = function () {
    // ...
};

return my;
};

Does the second block of code means that Module is just a function that itself returns an object?

IF I use the second variable like this

var ModuleObj = Module();

Will this work the same as the first Code block that I shared like IIFE.. Kind of confused...

Cumquat answered 6/2, 2016 at 5:37 Comment(0)
S
10

Yeah you pretty much got the idea of the difference between the two, let's look at why you might want one over the other.

An IIFE is useful to isolate the scope. It lets you keep the variables you define private inside the IIFE without polluting the global space around it. It's a nice way to compose a function that has some variables you don't need lurking around. Let's minimize this example a bit.

var Counter = (function () {
  var count = 0;

  var counter = {
    add: function () {
      count++;
    },
    subtract: function () {
      count--;
    },
    getCount: function () {
      return count;
    }
  }
  return counter;
})();

Counter.add();
Counter.add();
Counter.getCount(); // 2
Counter.subtract();
Counter.getCount(); // 1

What happens above is that we're able to compose this "counter" functionality without leaking the private information, like count. It'd be bad if other things could override it by accident. Also what happens is that right away we can assign Counter to the result of the IFFE -- the counter set of functions. Counter is now equal to that, and counter is able to retain access to count since it was defined in the same scope.

The benefit here is that we're able to assign a variable to this composition of functionality. The IIFE basically allows us to immediately return what we return inside of it. Since we assign Counter to the IIFE, and the IIFE returns the functionality inside of it, Counter is now a fully functional component.

We don't always have to use IIFE. It's really handy when you want to "tuck away" the implementation details and return an API.


So, what if we had the same thing, but it wasn't an IIFE -- just a function?

Just like your example, we'd have to call it in order to get the "instance".

var CounterFactory = function () {
  var count = 0;
  var counter = {
    add: //...
    subtract: //...
    getCount: //...
  };
  return counter;
};

var CounterA = CounterFactory();
var CounterB = CounterFactory();

CounterA.add();
CounterA.add();
CounterA.getCount(); // 2

CounterB.add();
CounterB.getCount(); // 1

See the difference? It's all about what the function is returning. In the first example we only get a single Counter instance, which may be perfectly fine. In the second example, it's more of a "factory" -- it generates an instance of counter and we can call that multiple times and get multiple instances of it.

Salena answered 6/2, 2016 at 5:56 Comment(0)
G
1

Ok an IIFE runs the functions within it and defines the variable MODULE to the return of that function. The other declares the MODULE variable to the function itself.

Think of it this way (also try it in your console to see the results).

This code does not run the console.log method.

(function(){
    console.log('ran')
});

This code does

(function(){
    console.log('ran')
})();

So the whole point of the IIFE is to run the function before doing anything and the (); at the end does this.

If we take the code that did not run and assign it to a value what happens?

var foo = (function(){
    console.log('ran')
});
foo();

We have a function foo that we can execute.

So what is the point of an IIFE if we can just assign it and run it later? The answer to that is local variables which you can use for closure later.

console.log(num); //get undefined
(function(){
    var num = 'ran';
    console.log(num) //get 'ran'
})();
console.log(num); //get undefined

We get undefined ran then undefined so the values we declare in the function stay in the function and nothing else can get to them. This is the lexical scoping that JavaScript runs off of.

Just for fun lets do a closure with it.

var add = (function(){
    var num = 0;
    return function(){
        console.log(num++);
    }
})();
console.log(num) //get undefined
add() //get 1
add() //get 2
console.log(num) //still undefined
Goyette answered 6/2, 2016 at 5:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.