heisthedon
heisthedon

Reputation: 3707

JavaScript Namespace Declaration

I created a javascript class as follow:

var MyClass = (function() {
   function myprivate(param) {
      console.log(param);
   }

   return {
      MyPublic : function(param) {
         myprivate(param);
      }
   };
})();

MyClass.MyPublic("hello");

The code above is working, but my question is, how if I want to introduce namespace to that class.

Basically I want to be able to call the class like this:

Namespace.MyClass.MyPublic("Hello World");

If I added Namespace.MyClass, it'll throw error "Syntax Error". I did try to add "window.Namespace = {}" and it doesn't work either.

Thanks.. :)

Upvotes: 30

Views: 14010

Answers (9)

user5311618
user5311618

Reputation:

To create new JavaScript namespaces (like Math), I personally define the following base class that can be extended, but not instantiated:

class Namespace {
    constructor() { throw TypeError("cannot instantiate a namespace") }
}

Subclasses will inherit constructor or override it with a method that calls super, so instantiation results in a TypeError either way.

The actual namespaces are defined by extending Namespace with any number of static properties (which can reference one another):

class ASCII extends Namespace {
    static whitespace = "\t\n\r\v ";
    static digits = "0123456789";
    static uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static lowers = ASCII.uppers.toLowerCase();
    static alphas = ASCII.uppers + ASCII.lowers;
    static alphanumerics = ASCII.alphas + ASCII.digits;
}

const isDigital = candidate => ASCII.digits.includes(candidate);

The example use a bunch of string constants, but a namespace can contain any types of value, including functions (defined as static methods).

Upvotes: 0

philrabin
philrabin

Reputation: 809

YUI has a nice method for declaring namespaces

if (!YAHOO) {
        var YAHOO = {};
}

YAHOO.namespace = function () {
    var a = arguments,
        o = null,
        i, j, d;
    for (i = 0; i < a.length; i = i + 1) {
        d = ("" + a[i]).split(".");
        o = YAHOO;
        for (j = (d[0] == "YAHOO") ? 1 : 0; j < d.length; j = j + 1) {
            o[d[j]] = o[d[j]] || {};
            o = o[d[j]];
        }
    }
    return o;
}

Place it above any function that you want to namespace like this:

YAHOO.namespace("MyNamespace.UI.Controls")

MyNamespace.UI.Controls.MyClass = function(){};
MyNamespace.UI.Controls.MyClass.prototype.someFunction = function(){};

This method is actually stand-alone and can easily be adapted to your application. Just find and replace "YAHOO" with your application's base namespace and you'll have something like MyOrg.namespace. The nice thing with this method is that you can declare namespaces at any depth without having to create object arrays in between, like for "UI" or "Controls"

Upvotes: 8

n_j_jaiganesh
n_j_jaiganesh

Reputation: 17

(function($){

    var Namespace =
{
    Register : function(_Name)
    {
        var chk = false;
        var cob = "";
        var spc = _Name.split(".");
        for(var i = 0; i<spc.length; i++)
        {
            if(cob!=""){cob+=".";}
            cob+=spc[i];
            chk = this.Exists(cob);
            if(!chk){this.Create(cob);}
        }
        if(chk){ throw "Namespace: " + _Name + " is already defined."; }
    },

    Create : function(_Src)
    {
        eval("window." + _Src + " = new Object();");
    },

    Exists : function(_Src)
    {
        eval("var NE = false; try{if(" + _Src + "){NE = true;}else{NE = false;}}catch(err){NE=false;}");
        return NE;
    }
}
    Namespace.Register("Campus.UI.Popup")
    Campus.UI.Popup=function(){
        defaults={
            action:'',
            ispartialaction:'',
            customcallback:'',
            confirmaction:'',
            controltoupdateid:'',
            width:500,
            title:'',
            onsubmit:function(id){
                var popupid=id+"_popupholder";
                if(this.ispartialaction){
                    $.ajax({
                        url:this.action,
                        type:"Get",
                        context:this,
                        success:function(data){
                            $('#'+id).parents('body').find('form').append("<div id'"+popupid+"'></div>");
                            var ajaxContext=this;
                            $("#"+popupid).dialog({
                                autoopen:false,
                                model:true,
                                width:this.width,
                                title:this.title,
                                buttons:{
                                    "Confirm":function(){
                                        if(ajaxContext.customcallback==''){
                                            var popupform=$(this).find("form");
                                            if(popupform.isValid()){
                                                $.post(ajaxContext.confirmaction,popupform.serialize(),function(d){
                                                    if(d!='')
                                                    {
                                                        $.each(d.Data,function(i,j){
                                                            switch(j.Operation)
                                                            {
                                                                case 1:
                                                                    if($('#'+j.ControlClientID).is("select"))
                                                                    {
                                                                        $('#'+j.ControlClientID).val(j.Value);
                                                                        $('#'+j.ControlClientID).change();
                                                                    }
                                                                    else if($('input[name="'+j.ControlClientID+'"]').length>0)
                                                                    {
                                                                        $('input[name="'+j.ControlClientID+'"][value="'+j.Value+'"]').prop("checked",true);
                                                                    }
                                                                    break;
                                                                case 2:
                                                                    if($('#'+j.ControlClientID).is("select"))
                                                                    {
                                                                        $('#'+j.ControlClientID).append("<option selected='selected' value=\""+j.Value+"\">"+j.Text+"</option>");
                                                                    }
                                                                    else
                                                                    {
                                                                        var len=$('input[name="'+j.ControlClientID+'"]').length;
                                                                        $('#'+j.ControlClientID+"list").append('<li><input type="checkbox" name="'+j.ControlClientID+'" value="'+j.Value+'" id="ae'+j.ControlClientID+len+'"/><label for "ae'+j.ControlClientID+len+'">'+j.Text+'</label>');
                                                                    }
                                                                    break;
                                                                case 0:
                                                                    $('#'+j.ControlClientID).val(j.Value);
                                                                    breakl
                                                                default:break;
                                                            }
                                                        });                                                                     

                                                        popupform.parent().dialog("destroy").remove();
                                                        $("#"+ajaxContext.controltoupdateid).change();
                                                    }
                                                });
                                            }
                                        }
                                        else
                                        {
                                            executeByFunctionName(ajaxContext.customcallback,window,new Array());
                                        }
                                    },
                                    "Cancel":function(){
                                        $(this).dialog("close");
                                    }
                                }
                            });
                            $("#"+popupid).dialog("open");
                            $("#"+popupid).empty().append(data);
                        },
                        error:function(e)
                        {
                            alert(e);
                        }
                    });
                }
                else
                {
                    var frm=document.createElement("form");
                    frm.id="CampusForm";
                    frm.name="CampusForm";
                    frm.action=this.action;
                    frm.method="post";
                    var arr=$($("#"+id).closest("body").find("form")).serializeArray();
                    $.each(arr,function(i,j){
                        var hidd=document.createElement("input");
                        hidd.type="hidden";
                        hidd.name=j.name;
                        hidd.value=j.value;
                        frm.appendChild(hidd);});
                    document.appendChild(frm);
                    frm.submit();
                }
            }
        },
        clicksubmit=function(){
            var opts=$(this).data("CampusPopup");
            opts.onsubmit($(this).attr("id"));
            return false;
        };
        return
        {
            init:function(opt){
                var opts=$.extend({},defaults,opt||{});
                $(this).data('CampusPopup',opts);
                $(this).bind("click",clicksubmit);
            }};
    }();
    $.extend({CampusPopup:Campus.UI.Popup.init});
})(jQuery)

Upvotes: 1

Justin
Justin

Reputation: 27331

This is the design pattern I use which allows for nested namespaces as well as adding to the namespace later (even from a separate JS file) so you don't pollute the global namespace:

Example: JsFiddle

(function ($, MyObject, undefined) {    
    MyObject.publicFunction = function () {
        console.log("public");
    };

    var privateFunction = function () {
        console.log("private");
    };

    var privateNumber = 0;
    MyObject.getNumber = function () {
        this.publicFunction();
        privateFunction();
        privateNumber++;
        console.log(privateNumber);
    };

    // Nested namespace
    MyObject.nested = MyObject.nested || {};
    MyObject.nested.test = function (text) {
        console.log(text);
    };    
}(jQuery, window.MyObject = window.MyObject || {}));

// Try it
MyObject.getNumber();
MyObject.nested.test('Nested');

Here is how to add to MyObject from another JavaScript file:

(function ($, MyObject, undefined) {
    MyObject.newFunction = function () {
        console.log("Added");
    };
}(jQuery, window.MyObject = window.MyObject || {})); 
// Pass `jQuery` to prevent conflicts and `MyObject` so it can be added to, instead of overwritten

This resource helped me learn all about the different JS design patterns: http://addyosmani.com/resources/essentialjsdesignpatterns/book/

Upvotes: 0

stamat
stamat

Reputation: 1979

Automating namespaces declaration in javascript is very simple as you can see:

var namespace = function(str, root) {
    var chunks = str.split('.');
    if(!root)
        root = window;
    var current = root;
    for(var i = 0; i < chunks.length; i++) {
        if (!current.hasOwnProperty(chunks[i]))
            current[chunks[i]] = {};
        current = current[chunks[i]];
    }
    return current;
};

// ----- USAGE ------

namespace('ivar.util.array');

ivar.util.array.foo = 'bar';
alert(ivar.util.array.foo);

namespace('string', ivar.util);

ivar.util.string.foo = 'baz';
alert(ivar.util.string.foo); 

Try it out: http://jsfiddle.net/stamat/Kb5xY/ Blog post: http://stamat.wordpress.com/2013/04/12/javascript-elegant-namespace-declaration/

Upvotes: 0

Tengiz
Tengiz

Reputation: 8449

bob.js has nice syntax to define JavaScript namespace:

bob.ns.setNs('myApp.myMethods', {
    method1: function() {
        console.log('This is method 1');
    },
    method2: function() {
        console.log('This is method 2');
    }
});
//call method1.
myApp.myMethods.method1();
//call method2.
myApp.myMethods.method2();

Upvotes: 1

bcherry
bcherry

Reputation: 7238

Usually I'd recommend doing this (assuming Namespace is not defined elsewhere):

var Namespace = {};
Namespace.MyClass = (function () {
  // ...
}());

A more flexible, but more complex, approach:

var Namespace = (function (Namespace) {
   Namespace.MyClass = function() {

       var privateMember = "private";
       function myPrivateMethod(param) {
         alert(param || privateMember);
       };

       MyClass.MyPublicMember = "public";
       MyClass.MyPublicMethod = function (param) {
          myPrivateMethod(param);
       };
   }
   return Namespace
}(Namespace || {}));

This builds Namespace.MyClass as above, but doesn't rely on Namespace already existing. It will declare and create it if it does not already exist. This also lets you load multiple members of Namespace in parallel in different files, loading order will not matter.

For more: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

Upvotes: 45

The Who
The Who

Reputation: 6622

Checkout the namespace library, it is very lightweight and easy to implement.

(function(){
   namespace("MyClass", MyPublic);

   function MyPublic(x){
     return x+1;
   }
})();

It supports automatically nesting as well

namespace("MyClass.SubClass.LowerClass", ....)

Would generate the necessary object hierarchy, if MyClass, SubClass did not already exist.

Upvotes: 2

Kevin Gorski
Kevin Gorski

Reputation: 3769

A succinct way to do what you're asking is create "Namespace" as an object literal like this:

var Namespace = {
    MyClass : (function() {
        ... rest of your module
    })();
};

This could cause conflicts if you wanted to attach other details to Namespace in other files, but you could get around that by always creating Namespace first, then setting members explicitly.

Upvotes: 3

Related Questions