普通のバージョン。

Namespace("org.example.net").apply(function(ns){
    return {
        HTTPRequest : function(){ console.log("ok");},
        HTTPResponse : function(){ console.log("ok");},
    };
});

Namespace("org.example.system").apply(function(ns){
    return {
        Console : {
            log : function(item){console.log(item)}
        },
    };
});

Namespace("org.example.application")
.use('org.example.net *')
.apply(function(ns){with(ns){
    var req = new HTTPRequest;
    var res = new HTTPResponse;
}});

Namespace("org.example.application")
.use('org.example.net *')
.use('org.example.system Console')
.apply(function(ns){with(ns){
    var req = new HTTPRequest;
    var res = new HTTPResponse;
    Console.log("ok");
}});


Namespace("org.example.application")
.use('org.example.net')
.use('org.example.system')
.apply(function(ns){with(ns){
    var req = new org.example.net.HTTPRequest;
    var res = new org.example.net.HTTPResponse;
    org.example.system.Console.log("ok");
}});

こんなふうに書きたくなったので、つくった。

var Namespace = (function(){
    /* utility */
    var merge = function(aObj,bObj){
        for( var p in bObj ){
            if( bObj.hasOwnProperty( p ) ){
                aObj[p] = bObj[p];
            }
        }
        return aObj;
    };
    /* inner class of namespace*/
    var _Namespace = (function(){
        var nsCache = {};
        var nsList  = [];
        /* constructor*/
        var Klass = function _Private_Class_Of_Namespace(fqn){
            this._useList = [];
            this._stash   = {
                CURRENT_NAMESPACE : fqn
            };
        };
        /* private functions */
        var _loadStash = function(ns){
            if(!nsCache[ns]) throw('undefined namespace:' + ns);
            return nsCache[ns]._stash;
        };
        var _loadStashItem = function(ns,itemName){
            var nsStash = _loadStash(ns);
            if(typeof(nsStash[itemName]) === 'undefined') throw('undefined item:' +ns+'#'+itemName);
            return nsStash[itemName];
        };

  
        var _mergeUseData = (function(){
            var _loadImport = function(ns,imports){
                var retStash = {};
                for(var i = 0,l=imports.length;i<l;i++){
                    var importSyntax = imports[i];
                    if( importSyntax === '*' ) return _loadStash(ns);
                    retStash[importSyntax] = _loadStashItem(ns,importSyntax);
                }
                return retStash;
            };
            var _mergeWithNS = function(stash,ns){
                var nsList = ns.split(/\./);
                var current = stash;
                for(var i = 0,l=nsList.length;i<l-1;i++){
                    if( !current[nsList[i]] ) current[nsList[i]] = {};
                    current = current[nsList[i]];
                }
                current[nsList[nsList.length-1]] = _loadStash(ns);
            };
            return function(stash,useData){
                if( useData.import ){
                    merge( stash , _loadImport(useData.ns,useData.import));
                }else{
                    _mergeWithNS(stash,useData.ns);
                }
            };
        })();
        var _assertValidFQN = function(fqn){
            if( !fqn.match(/^[a-z][a-z0-9.]+[a-z0-9]$/) ){
                throw('Invalid namespace');
            }
        };
        
        /* extend prototype */
        (function(){
            var _composeStash = function(that){
                var stash = {};
                for(var i = 0,l= that._useList.length;i<l;i++) _mergeUseData( stash, that._useList[i]);
                return merge( stash , that._stash );
            };
            this.use = function(){
                for(var i = 0,l=arguments.length;i<l;i++){
                    var splittedUseSyntax = arguments[i].split(/\s/);
                    var fqn = splittedUseSyntax[0];
                    var imp = splittedUseSyntax[1];
                    var importNames = (imp) ? imp.split(/,/): null;
                    _assertValidFQN(fqn);
                    this._useList.push({ ns: fqn,import: importNames });
                }
                return this;
            };
            this.apply = function(callback){
                merge(this._stash,callback(_composeStash(this))||{});
                this._useList = [];
                return this;
            };
            this.define = function(obj){
                return this.apply(function(){return obj});
            };
        }).apply(Klass.prototype);
        
        /* public interface */
        return {
            create :function(fqn){
                 _assertValidFQN(fqn);
                if( nsCache[fqn] ){
                    return nsCache[fqn];
                }
                var ns = nsCache[fqn] = new Klass(fqn);
                return ns;

            }
        };
    })();
    return function(nsString){
        return _Namespace.create(nsString);
    };
})();