Re one of the [higher level] reasons why they are important:
So in OO languages (Like Java or C#), variables/methods are scoped to a class. They don’t leak out unless you explicitly make them leak out, and you expose properties/methods to the outside world via some interface. In functional languages, modules perform a similar role - variables/functions are scoped to that module, with something that makes explicit what is exported/exposed to the outside world.
JS used to have neither of these things (it now has modules - note classes in JS are something different, & do not really allow private scoped variables/methods). It does have function scope though, so by using IIFEs, you can make the equivalent of a module which has private variables that do not leak out into the global scope.
// taken from https://addyosmani.com/resources/essentialjsdesignpatterns/book/
var myRevealingModule = (function () {
var privateVar = "Ben Cherry";
var publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
This pattern allows the syntax of our scripts to be more consistent. It also makes it more clear at the end of the module which of our functions and variables may be accessed publicly which eases readability.
Note that module bundlers often work by basically just compiling JS modules to IIFEs