Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Namespace

I want to create a global namespace for my application and in that namespace I want other namespaces:

E.g.

Dashboard.Ajax.Post()

Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent();

I also want to place them in seperate files:

  • Ajax.js
  • RetrieveContent.js

However I have tried using this method, however it won't work because the same variable name is being used for the namespace in 2 seperate places. Can anyone offer an alternative?

Thanks.

like image 498
Jamie C Avatar asked Aug 05 '10 00:08

Jamie C


4 Answers

You just need to make sure that you don't stomp on your namespace object if it's already been created. Something like this would work:

(function() {
    // private vars can go in here


    Dashboard = Dashboard || {};
    Dashboard.Ajax = {
        Post: function() {
            ...
        }
    };
})();

And the RetrieveContent file would be defined similarly.

like image 162
Gabe Moothart Avatar answered Sep 29 '22 17:09

Gabe Moothart


Here is a very good article on various "Module Patterns" in JavaScript. There is a very nice little section on how you can augment modules, or namespaces and maintain a cross-file private state. That is to say, the code in separate files will be executed sequentially and properly augment the namespace after it is executed.

I have not explored this technique thoroughly so no promises... but here is the basic idea.

dashboard.js

(function(window){

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

        function privateMethod() { 
            // ... 
        } 

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

        return my; 
    }());

    window.Dashboard = dashboard;
})(window);

dashboard.ajax.js

var dashboard = (function (my) { 
    var _private = my._private = my._private || {}, 
        _seal = my._seal = my._seal || function () { 
            delete my._private; 
            delete my._seal; 
            delete my._unseal; 
        }, 
        _unseal = my._unseal = my._unseal || function () { 
            my._private = _private; 
            my._seal = _seal; 
            my._unseal = _unseal; 
        }; 

    // permanent access to _private, _seal, and _unseal

    my.ajax = function(){ 
        // ...
    }

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

dashboard.retrieveContent.js

var dashboard = (function (my) { 
    var _private = my._private = my._private || {}, 
        _seal = my._seal = my._seal || function () { 
            delete my._private; 
            delete my._seal; 
            delete my._unseal; 
        }, 
        _unseal = my._unseal = my._unseal || function () { 
            my._private = _private; 
            my._seal = _seal; 
            my._unseal = _unseal; 
        }; 

    // permanent access to _private, _seal, and _unseal

    my.retrieveContent = function(){ 
        // ...
    }

    return my; 
}(dashboard || {}));
like image 39
Derek Adair Avatar answered Sep 29 '22 18:09

Derek Adair


The Yahoo Namespace function is exactly designed for this problem.

Added:

The source of the function is available. You can copy it into your own code if you want, change the root from YAHOO to something else, etc.

like image 4
Larry K Avatar answered Sep 29 '22 19:09

Larry K


There are several libraries that already offer this sort of functionality if you want to use or examine a pre-baked (that is, a tested) solution.

  • YUI.attribute and YUI.base
  • dojo.mixin
  • underscore.extend
  • jQuery.extend
  • goog.provide and goog.object.extend

The simplest and most bug free one to get going with is probably jQuery.extend, with the deep argument set to true. (The reason I say it is bug free is not because I think that jQuery.extend suffers from less bugs than any of the other libraries -- but because it offers a clear option to deep copy attributes from the sender to the receiver -- which most of the other libraries explicitly do not provide. This will prevent many hard-to-diagnose bugs from cropping up in your program later because you used a shallow-copy extend and now have functions executing in contexts you weren't expecting them to be executing in. (If however you are cognizant of how you will be extending your base library while designing your methods, this should not be a problem.)

like image 3
Sean Vieira Avatar answered Sep 29 '22 18:09

Sean Vieira