JavaScript 命名空间声明

30

我创建了一个如下的 JavaScript 类:

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

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

MyClass.MyPublic("hello");

上述代码可以运行,但我的问题是,如果我想为该类引入命名空间怎么办。

基本上我想要这样调用该类:

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

如果我添加了Namespace.MyClass,它会抛出“语法错误”的错误。

我尝试添加“window.Namespace = {}”,但也不起作用。

谢谢.. :)


完全重复... https://dev59.com/IXNA5IYBdhLWcg3wpfmu - Jaco Pretorius
9个回答

45

通常我会建议这样做(假设Namespace在其他地方没有定义):

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

一种更灵活但更复杂的方法:

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 || {}));

这样构建Namespace.MyClass,不依赖于Namespace已经存在。如果不存在,它会声明并创建它。这还允许您在不同的文件中并行加载Namespace的多个成员,加载顺序将不重要。

更多信息请参阅: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth


(Namespace || {}); 的意思是什么? - oktomus

8

YUI有一个不错的方法来声明命名空间

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;
}

将其放在您想要命名空间的任何函数上方,如下所示:

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

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

这个方法其实是独立的,可以轻松地适用于您的应用程序。只需找到并替换“YAHOO”为您的应用程序的基本命名空间,您就会得到类似于MyOrg.namespace的东西。这个方法的好处在于,您可以在任何深度上声明命名空间,而无需创建对象数组,比如“UI”或“Controls”。


3
一个简洁的做法是创建一个对象字面量作为命名空间,代码如下:

“Namespace”:

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

这可能会导致冲突,如果您想在其他文件中附加其他细节到命名空间。但是,您可以通过始终首先创建命名空间,然后显式设置成员来解决这个问题。

2

请查看命名空间库(namespace library),它非常轻便易用。

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

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

它还支持自动嵌套

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

如果MyClass和SubClass不存在,那么将生成必要的对象层次结构。

1

bob.js有很好的语法来定义JavaScript命名空间:

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();

1
(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)

0
在JavaScript中自动声明命名空间非常简单,正如您所看到的:


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); 

试一下:http://jsfiddle.net/stamat/Kb5xY/ 博客文章:http://stamat.wordpress.com/2013/04/12/javascript-elegant-namespace-declaration/


0

这是我使用的设计模式,它允许嵌套命名空间,并且稍后可以添加到命名空间中(甚至来自单独的JS文件),因此您不会污染全局命名空间:

示例: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');

以下是如何从另一个 JavaScript 文件向 MyObject 添加内容:

(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

这个资源帮助我学习了所有不同的JS设计模式:http://addyosmani.com/resources/essentialjsdesignpatterns/book/


0

为了创建新的JavaScript命名空间(例如Math),我个人定义了以下基类,可以被扩展但不能被实例化:

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

子类会继承constructor或通过调用super覆盖它的方法,因此实例化方式无论哪种都会导致TypeError

实际命名空间是通过使用任意数量的静态属性(可以互相引用)扩展Namespace来定义的:

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);

这个例子使用了一堆字符串常量,但是命名空间可以包含任何类型的值,包括函数(定义为静态方法)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接