5

In a Udacity lesson on immediately invoked function expressions (regarding the provided code snippet) it says:

The function that is being returned closes over (i.e., captures) the hi variable. This allows myFunction to maintain a private, mutable state that cannot be accessed outside the function! What's more: because the function expressed is called immediately, the IIFE wraps up the code nicely so that we don't pollute the global scope.

I'm strugggling to understand what calling the anonymous function immediately has to do with prevent the variable hi from "polluting the global scope," and since hi is already defined in a function, isn't it already in local/private scope?

const myFunction = (
  function () {
    const hi = 'Hi!';
    return function () {
      console.log(hi);
    }
  }
)();
nCardot
  • 5,992
  • 6
  • 47
  • 83
  • The point is to avoid having `hi` be accessible from global scope, and creating yet another name that can't be conflicted with. – Patrick Roberts Jun 20 '18 at 05:23
  • 1
    Possible duplicate of [JavaScript design pattern: difference between module pattern and revealing module pattern?](https://stackoverflow.com/questions/22906662/javascript-design-pattern-difference-between-module-pattern-and-revealing-modul) – Patrick Roberts Jun 20 '18 at 05:26
  • 1
    If you didn't call it immediately, you'd have to give it a name, polluting the outer scope. – melpomene Jun 20 '18 at 06:15
  • basically `myFunction = function () { console.log(hi) }` because it's the result of the iife but if you don't use an iife you will have to have declared `hi` in the outer scope. If you do this in the highest scope you end up with `hi` being in your `window` object or `global` object (depending on what you have) thus polluting it. – apokryfos Jun 20 '18 at 06:31
  • As long as a variable is within a block (in the case of let or const) or function (in the case of car), it doesn't pollute global scope – nCardot Jun 21 '18 at 15:00

2 Answers2

4

In modern JavaScript, you have let and block scope (and I'm pretty sure const has block scope, too), so you could just do this:

let myFunction;
{
    let hi = 'Hi!';
    myFunction = function () {
        console.log(hi);
    };
}

This creates myFunction without leaking hi into the surrounding scope.

In traditional JavaScript, where you only have var and function scope, you could do this:

var myFunction;
function a_private_scope() {
    var hi = 'Hi!';
    myFunction = function () {
        console.log(hi);
    };
}
a_private_scope();

a_private_scope limits the scope of hi, but (it being a function declaration) it needs to be called explicitly, and we still leak a name to the surrounding scope (this time it's a_private_scope, the name of the function-serving-as-a-scope).

By using a function expression and immediately calling it, we avoid this second name pollution:

var myFunction;
(function () {
    var hi = 'Hi!';
    myFunction = function () {
        console.log(hi);
    };
})();

Now the only thing defined in the outer scope is myFunction. The anonymous function that serves as a scope for hi has no name it could pollute the surrounding scope with.

Finally we can clean it up a bit by using return values, so we don't have to mention myFunction twice:

var myFunction = function () {
    var hi = 'Hi!';
    return function () {
        console.log(hi);
    };
}();

(This also saves us a pair of ( ) because the function keyword doesn't appear at the beginning of a statement anymore.)

melpomene
  • 84,125
  • 8
  • 85
  • 148
0

How does an IIFE's being called immediately prevent it from polluting global scope?

It doesn't.

Being a function stops it polluting the global scope.

Variables declared inside a function exist only within that function

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 1
    They why need an iife? We can just use normal functions? Why an iife is said to be preventing global scope pollution? – Kumar Manish Jul 08 '18 at 08:53
  • You don't need an IIFE. You can use a normal function (but you would have to call it *sometime* so why not immediately?). Look at the last two sentences of the answer again. – Quentin Jul 08 '18 at 08:56
  • Everyone knows that! The point is not THAT! The point is that one of the advantages of IIFE's are mentioned as that they do not pollute global scope! How can you guys not see the difference! Why do they do that when it happens in normal function too! – Kumar Manish Jul 08 '18 at 15:34
  • The only difference is that instead of writing "function funcName() { whatever; } funcName();" you write "(function () { whatever; })();" which avoids leaving funcName lying around. It's a tiny thing, but in a large project with lots and lots of one-use functions it might protect you from accidental function name reuse. – Foo Bar Dec 10 '18 at 18:19