Last Updated: September 09, 2019
·
6.231K
· gerardsans

JavaScript - Module pattern

Sons of JavaScript Collection | this article

This pattern gets more important as your team or JavaScript code base grows in size. It uses previous patterns
- Namespaces
- Immediate functions
- Encapsulation

Basic form (using literal notation)

var MyApp = {};
MyApp.MyModule = (function() {
   var privateVariable = 1;
   var publicVariable = 2;
   var publicFunction = function() {return 3;}
   return {
      publicVariable: publicVariable,
      publicFunction: publicFunction
   };
})();
console.log(MyApp.MyModule.privateVariable); //undefined
console.log(MyApp.MyModule.publicVariable); //2
console.log(MyApp.MyModule.publicFunction() ); //3

Basic form (using an object)

var MyApp = {};
MyApp.MyModule = (function() {
   var module = {};
   var privateVariable = 1;
   module.publicVariable = 2;
   module.publicFunction = function() {return 3;}
   return module;
})();
console.log(MyApp.MyModule.privateVariable); //undefined
console.log(MyApp.MyModule.publicVariable); //2
console.log(MyApp.MyModule.publicFunction() ); //3

We achieve encapsulation by using a clousure (Immediate Function) and deciding what properties are visible to the parent scope. As we saw, clousures store the local variables scope at the time of execution. Here is when we call the immediate function.

Advanced form (using parameter injection)

Sometimes we need an initial state or dependencies. We can use the Immediate Function parameters to achieve that.

var MyApp = {};
var config = {a:1};
MyApp.MyModule = (function(config) {
     return {
       MyVariable: config.a || 2
     };
})(config);
console.log(MyApp.MyModule.MyVariable); // 1

Notes

Besides the basic Module Pattern you may want to look into more complex module systems:

  • CommonJS Modules (server, Node.js) - or
  • Asynchronous Module Definition (AMD, browser)

Before using them take some time to evaluate if they help to solve your specific scenario as they come with some extra overhead. You can start looking here or the links below.
Writing Modular JavaScript With AMD, CommonJS & ES Harmony

More information

ECMAScript 6 modules: the final syntax

"Learning JavaScript Design Patterns", the Module Pattern, Addy Osmani 2014

"Mastering the Module Pattern", Todd Motto

Sons of JavaScript Collection | this article

16 Responses
Add your response

Why not just use what is available, like RequireJS or CommonJS to achieve a modularized system. That would be much easier in terms of setup and would not need objects in objects and scope isolation.

I have used this technique before as well and i like the AMD method a lot better.

Especially on big projects it gets so messy. I do really like the revealing module pattern though and would definitely recommend that, but i would do it with requirejs to not have to worry about if i can access a module or not and can easily create seperate modules that do not have to be bound to a myApp object for instance.

over 1 year ago ·

Honestly this tip seems kinda outdated, as nowadays we have these module systems:

  • CommonJS (used by node.js server-side, that can be brought to browsers using browserify bundling tool)

  • AMD (Async Module Definition, supported by tools like RequireJS)

  • UMD (Universal Module Defintion, a syntax that supports CommonJS, AMD, and vanilla browser globals, browserify can produce UMD modules)

  • EcmaScript6 modules, probably the most elegant (and it's the upcoming standard), the downside is for current browsers it requires a transpilation step, eg. using Traceur (partial), or browserify with an ES6 plugin (probably the best option at the moment of this writing)

over 1 year ago ·

Closure and encapsulation are not the same thing, and closures do not store the scope at the time of execution, then have a scope collection reference and a local scope collection at the time of compilation. by the time execution comes around, it's a whole 'nuther ball game.

over 1 year ago ·

I use require JS / AMD which provides isolation of my module variables and prevent them from polluting global namespace.

over 1 year ago ·

Thanks for your comments. These libraries are not of my interest for what I wanted to show.

over 1 year ago ·

If you just want that you don't really need them.

over 1 year ago ·

I recommend you reading Mozilla docs on closures. Private members are achieved by closures. Which is the base of encapsulation.

over 1 year ago ·

AMD says it all async module definition. Is that what you want? You probably don't need it.

over 1 year ago ·

In Javascript, closures create scopes. Scopes are a stateful thing. Encapsulation is not. You can have something that seems encapsulated, but in truth what you have is a state that no longer exists and it's members are no longer accessible because it doesn't exist.

"These libraries are not my interest in what I want to show"

They're not libraries, they're patterns for js module development And what you are trying to show is an incorrect implementation of the module pattern.

Several experienced developers have tried to tell you in polite ways that you're doing it wrong. But now I'm just going to say it. You don't have a strong enough grasp of the language to be putting forth educational material. This can cause problems to those who read it and trust that you DO know what you are talking about, when in fact you don't.

You're pumping out harmful educational material faster than those trying to help you can point out the flaws, and you continue with new material despite being informed that your existing material is incorrect.

over 1 year ago ·

You should stop trolling. Some other sources where you can see the very SAME pattern being used.

"Learning JavaScript Design Patterns", the Module Pattern, Addy Osmani 2014

"Mastering the Module Pattern", Todd Motto

over 1 year ago ·

Trolling? Trying to help you is trolling? And did you think I wouldn't notice when you literally replaced your entire article, and instead of thanking those who tried to help, you called them trolls, and then threw the source links for your plagiarism in our faces. You changed the property names of the demonstrations in Todd's article and put your name on it.

This community will help you if you don't call them trolls and give them and be rude (what you basically did to @benjamine), and you wouldn't have been scorned for fixing your own work.

over 1 year ago ·

Why would I need to copy the code or replace it? It looks the same because is the SAME pattern. I'm sharing the code to help other developers. Best wishes. Have a lovely day.

over 1 year ago ·

I guess @longlivechief said it all, I just wanted to clarify my comment is not trolling, more like the opposite, I was trying to prevent future readers from making the same mistakes I did in the past (I've used this module pattern, then AMD (require.js), and then CommonJS (browserify).
A response expected in any mature online community is: you get comments that try to correct/improve on the subject, read a little about them and update your article if appropriate.
Learning is a process that requires a lot of humbleness, and I like to think the biggest purpose of this tips is help the future readers. Regards.

over 1 year ago ·

I see. That's what it seems to me. I did not invented the Module Pattern. You don't like it. It's fine. I believe is useful and backed up from many sources. I really don't understand why all this fuss. Use whatever you like. Even better add your own pro tip about it. These comments add no value and only makes everybody waste their time. Classic trolling in my book.

over 1 year ago ·

I'd have to agree with the "trolls" about the AMD pattern being a more robust approach. In most real world apps your dependencies will be distributed across different files, and AMD helps you eliminate the need of having to define dependencies in specific order

over 1 year ago ·

Thanks for giving your opinion.

This protip is about the Module Pattern and not against AMD. AMD solves more complex scenarios. Please follow links for more information on AMD.

over 1 year ago ·