1

Just learned about JavaScript module pattern. Love it!

So, I created my generic custom library which is located in one file which I include on all my projects. I then want to add a couple project specific methods for each individual project, and would like to put them in a separate file. Instead of creating a whole new object for these methods, I would like to add them to my existing MODULE object.

How do I do this? Thanks

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

    function privateMethod() {
        // ...
    }

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

    return my;
}());
user1032531
  • 24,767
  • 68
  • 217
  • 387
  • Without explaining what all the properties/methods do in your module, just use `MODULE.whateverYouWant = whatever;` in your specific places – Ian Apr 02 '13 at 23:36
  • `MODULE.foo = "foo"` ?? – elclanrs Apr 02 '13 at 23:37
  • Thanks Ian and Elclanrs. So, I do not need the closure parenthesis? – user1032531 Apr 02 '13 at 23:43
  • @user1032531 No, you can keep those, to keep a specific scope when **declaring** `MODULE`. But if you want to add properties/methods to it later (outside of that file), you can just say `MODULE.whatever = whatever;` – Ian Apr 02 '13 at 23:46
  • @Ian. And will the namespace for MODULE.whatever be the same as my original methods? – user1032531 Apr 02 '13 at 23:49
  • @user1032531 So after your declaration of `MODULE`, it will look like: `{moduleProperty: 1, moduleMethod: function () { }}`. When you use what we're saying, it will look like: `{moduleProperty: 1, moduleMethod: function () { }, whatever: "whatever"}`. Is that what you mean? Setting them this way, these new things won't have access to private things like `privateVariable` and `privateMethod` – Ian Apr 02 '13 at 23:51
  • @Iam. Don't know if I really need to have access to privateVariable or privateMethod, but yes that was my intention to be able to, and have the new methods seem the same as the initial ones. – user1032531 Apr 02 '13 at 23:57

1 Answers1

5

You can add a property or function by just saying Module.namedproperty = ...whatever...

But it should be noted that if this is in a different file it won't have access to any private variables in the module state.

If you want to have additional private state for these new methods, or want to not worry about which file is run first you can set up your modules like this

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

    function privateMethod() {
        // ...
    }

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

    return my;
}(MODULE||{}));

Which will create a new module if the module hasn't been created yet, or add to the existing one if it has.

The private variables will still be private to their own particular closure though, and not to the namespace/module as a whole.

Update to explain

This module format takes in an input into its closure function. If MODULE is already defined, it takes in the MODULE object, otherwise it creates a new empty object. || is logical OR, so MODULE||{} is the same as "if MODULE is defined and is truthy (which an object like MODULE will be), then pass it, if it is undefined or otherwise falsy, pass an empty object.

The extra parentheses are not strictly necessary, but they're a convention to make it clear that the result of the function is being passed, not the function itself.

Ben McCormick
  • 25,260
  • 12
  • 52
  • 71
  • I think you are on the right path, but don't know if this is exactly correct. Why have the open parenthesis in the very beginning and the closing parenthesis at the very end? Can you explain what is happening? For instance, if object MODULE doesn't exist, then create a new one, else pass something to the existing one... – user1032531 Apr 03 '13 at 00:03
  • I actually think you are now correct since it works! Please still explain what is happening. – user1032531 Apr 03 '13 at 00:05
  • The extra parenthesis are for readability. If you see `...=(function(){...` then you can be fairly certain you are reading an immediately invoked function expression (IIFE). If you see `=function(){...` then it's not until you see the closing `}();` that you realise it's an IIFE rather than a plain function expression. Of course you can enclose a function expression in parenthesis and not call the function, but that's just making life difficult. – RobG Apr 03 '13 at 00:15
  • @user1032531 updated to explain. You can also check out more here: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html – Ben McCormick Apr 03 '13 at 00:15
  • if the first module on an another file, to which this adds to, was written using the same pattern `var MODULE = (function (my) {...}(MODULE||{}));` may we ignore the loading order of files? Is this the trick to not to worry about file loading order? – João Pimentel Ferreira Nov 20 '18 at 22:44