140

I can't find any accessible examples showing how two (or more) different modules are connected to work together.

So, I'd like to ask whether anyone has time to write an example explaining how modules work together.

Seanny123
  • 8,776
  • 13
  • 68
  • 124
Srle
  • 10,366
  • 8
  • 34
  • 63
  • This has all changed in the last four years, but thanks to the zealous over-moderation, this out-of-date info will hang around *forever*. Here's [MDN's page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) on ES6 modulels. – bbsimonbb Apr 12 '17 at 07:27

5 Answers5

265

In order to approach to Modular design pattern, you need to understand these concept first:

Immediately-Invoked Function Expression (IIFE):

(function() {
      // Your code goes here 
}());

There are two ways you can use the functions. 1. Function declaration 2. Function expression.

Here are using function expression.

What is namespace? Now if we add the namespace to the above piece of code then

var anoyn = (function() {
}());

What is closure in JS?

It means if we declare any function with any variable scope/inside another function (in JS we can declare a function inside another function!) then it will count that function scope always. This means that any variable in outer function will be read always. It will not read the global variable (if any) with the same name. This is also one of the objective of using modular design pattern avoiding naming conflict.

var scope = "I am global";
function whatismyscope() {
    var scope = "I am just a local";
    function func() {return scope;}
    return func;
}
whatismyscope()()

Now we will apply these three concepts I mentioned above to define our first modular design pattern:

var modularpattern = (function() {
    // your module code goes here
    var sum = 0 ;

    return {
        add:function() {
            sum = sum + 1;
            return sum;
        },
        reset:function() {
            return sum = 0;    
        }  
    }   
}());
alert(modularpattern.add());    // alerts: 1
alert(modularpattern.add());    // alerts: 2
alert(modularpattern.reset());  // alerts: 0

jsfiddle for the code above.

The objective is to hide the variable accessibility from the outside world.

starball
  • 20,030
  • 7
  • 43
  • 238
kta
  • 19,412
  • 7
  • 65
  • 47
  • would it be better to name the iife? for semantic purposes and better stack tracing? would it change anything in the code? – Jeroen Oct 14 '14 at 08:43
  • 2
    Your first example `(function() { /* Your code goes here */}());` is actually a IIFE (Immediately Invoking Function Expression), ok it's anonymous coz it has no name so you may even want to call it an IIAFE (Immediately Invoking Anonymous Function Expression) see more on IIFE on http://stackoverflow.com/questions/2421911/what-is-the-purpose-of-wrapping-whole-javascript-files-in-anonymous-functions-li/26738969#26738969 – Adriano Nov 13 '14 at 15:13
  • why return statement has been used ? if we omit return {} then add and reset function would be public and i guess they can access local variable sum ? am i right? – Mou May 12 '15 at 11:15
  • your second example looks like an object or i am not right ? – The Reason May 27 '15 at 15:20
  • @kta - The link you specified is not working. Can you please fix it. Thanks. – user1176058 Jul 30 '15 at 15:27
  • 4
    This doesn't address the OP's question. It is a description of the module pattern not an example of how multiple modules can work together as the OP wanted. – Erik Trautman Sep 01 '15 at 23:37
  • What you call an *Anonymous Function* in the first code listing is an [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression). This is an anonymous function: `function () { .... }` – sampathsris Dec 04 '15 at 05:01
  • Hi KTA, I was just trying to understand the block of code which you posted..but i was not able to get this : why you have used two parenthesis whatismyscope()() while calling whatismyscope function. – 5eeker Jun 08 '17 at 06:10
  • @5eeker The first pair of parentheses calls whatismyscope, and the second pair calls the function whatismyscope() returns. – R.J. Dunnill Jan 16 '19 at 23:18
  • @R.J.Dunnill Cool, thanks man – 5eeker Jan 17 '19 at 09:14
  • Thank you, Your explanation just show me how `the connect in react works`, after many months trying to figure out if react-redux connect was actually written in javascript, finally, I got it module pattern. `connect(mapStateToProps, mapDispatchToProps)(Component).` – Akolade Adesanmi Jul 10 '19 at 13:56
  • @akolliy - thanks for your response! – kta Jul 10 '19 at 22:45
40

I would really recommend anyone entering this subject to read Addy Osmani's free book:

"Learning JavaScript Design Patterns".

http://addyosmani.com/resources/essentialjsdesignpatterns/book/

This book helped me out immensely when I was starting into writing more maintainable JavaScript and I still use it as a reference. Have a look at his different module pattern implementations, he explains them really well.

Pure Function
  • 2,129
  • 1
  • 22
  • 31
  • I'd also recommend reading my article on the "Definitive Module Pattern" which is not covered in Addy Osmani's book: https://github.com/tfmontague/definitive-module-pattern – tim-montague Jul 07 '14 at 07:51
  • 1
    How does this compare to "JavaScript Patterns" by Stoyan Stefanov – JohnMerlino Aug 18 '14 at 01:20
  • 4
    Stoyan's book is much more comprehensive. It covers more than just high level patterns but also talks more in-depth about other JS best practices. – Pure Function Aug 18 '14 at 02:17
  • 1
    reviews of "Learning JavaScript Design Patterns" http://www.amazon.com/product-reviews/1449331815/ – Adriano Sep 15 '14 at 14:53
  • 3
    reviews of "JavaScript Patterns" by Stoyan Stefanov http://www.amazon.com/product-reviews/0596806752 . Note: which seem much better than the one from "Learning JavaScript Design Patterns" – Adriano Sep 15 '14 at 15:01
19

I thought i'd expand on the above answer by talking about how you'd fit modules together into an application. I'd read about this in the doug crockford book but being new to javascript it was all still a bit mysterious.

I come from a c# background so have added some terminology I find useful from there.

Html

You'll have some kindof top level html file. It helps to think of this as your project file. Every javascript file you add to the project wants to go into this, unfortunately you dont get tool support for this (I'm using IDEA).

You need add files to the project with script tags like this:

        <script type="text/javascript" src="app/native/MasterFile.js" /></script>
        <script type="text/javascript" src="app/native/SomeComponent.js" /></script>

It appears collapsing the tags causes things to fail - whilst it looks like xml it's really something with crazier rules!

Namespace file

MasterFile.js

myAppNamespace = {};

that's it. This is just for adding a single global variable for the rest of our code to live in. You could also declare nested namespaces here (or in their own files).

Module(s)

SomeComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

    var incrementCount = function () {
        privateState += 1;
    };

    return function (message) {
        incrementCount();
        //TODO something with the message! 
    }
})();

What we're doing here is assigning a message counter function to a variable in our application. It's a function which returns a function which we immediately execute.

Concepts

I think it helps to think of the top line in SomeComponent as being the namespace where you are declaring something. The only caveat to this is all your namespaces need to appear in some other file first - they are just objects rooted by our application variable.

I've only taken minor steps with this at the moment (i'm refactoring some normal javascript out of an extjs app so I can test it) but it seems quite nice as you can define little functional units whilst avoiding the quagmire of 'this'.

You can also use this style to define constructors by returning a function which returns an object with a collection of functions and not calling it immediately.

JonnyRaa
  • 7,559
  • 6
  • 45
  • 49
6

Here https://toddmotto.com/mastering-the-module-pattern you can find the pattern thoroughly explained. I would add that the second thing about modular JavaScript is how to structure your code in multiple files. Many folks may advice you here to go with AMD, yet I can say from experience that you will end up on some point with slow page response because of numerous HTTP requests. The way out is pre-compilation of your JavaScript modules (one per file) into a single file following CommonJS standard. Take a look at samples here http://dsheiko.github.io/cjsc/

kevinarpe
  • 20,319
  • 26
  • 127
  • 154
Dmitry Sheiko
  • 2,130
  • 1
  • 25
  • 28
  • All the AMD implementations also provide precompilation into a single file. – I-Lin Kuo Aug 11 '14 at 12:05
  • 1
    That is correct, but the resulting optimized file requires the loader library (just re-checked it with r.js v2.1.14), which is usually quite weighty. As soon as we have compiled code we do not need resolving asynchronously loaded dependencies, we do not need this library. Just consider: we wrap modules into AMD, that means async. loading, then compile them into a single file (no separate loading anymore), but load the entire library to address them (what's redundant now). It doesn't sounds as an optimal way to me. Why AMD at all when we don't load asynchronously? – Dmitry Sheiko Aug 12 '14 at 10:29
  • almond.js provides a smaller weight loader for finished production code than RequireJS, but comparatively speaking, the performance benefit of not making just a single http request far outweighs the cost of adding the loader code to the module, so while it's less optimal, it's at a much smaller scale. The question, in my opinion, ought to be turned around -- why assume synchronicity when the browser isn't? I'm actually of the opinion that both RequireJS and CommonJS ought to have a promise implementation built in. – I-Lin Kuo Aug 12 '14 at 11:29
  • Both formats are valid paths to CommonJS Modules/2.0 and provide the same scalability. As to me - dealing with CJS Modules/1.1 (that's what I mean by CommonJS) is much easier, code looks cleaner. – Dmitry Sheiko Aug 12 '14 at 12:01
  • I have met such benefits of AMD as: * can load more than just JavaScript files; * path aliases; Well, CommonJS Compiler solves these - it loads non-JavaScipt/JSON dependencies as data and can be provided with build configuration (including aliases). The only disadvantage that it requires building. But nowadays everybody anyway builds the project for CSS pre-processors. So it is just about adding an extra task for Grunt/Gulp... – Dmitry Sheiko Aug 12 '14 at 12:01
  • I had to mention AMD's flexibility. You can, for instance, load synchronously combined scripts delivering core experience and enhance UX with asynchronously loaded other scripts. With CJS it's still achievable but way less elegant. – Dmitry Sheiko Aug 12 '14 at 12:15
-3

You can find Module Pattern JavaScript here http://www.sga.su/module-pattern-javascript/

Roman
  • 1,336
  • 15
  • 17