【问题标题】:JavaScript Namespace DeclarationJavaScript 命名空间声明
【发布时间】:2011-01-31 01:35:05
【问题描述】:

我创建了一个 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 = {}”,但它也不起作用。

谢谢.. :)

【问题讨论】:

标签: javascript


【解决方案1】:

按照您的要求,一种简洁的方法是将“命名空间”创建为像这样的对象文字:

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

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

【讨论】:

    【解决方案2】:

    通常我建议这样做(假设 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 || {});是什么意思?
    【解决方案3】:

    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”或“控件”

    【讨论】:

      【解决方案4】:

      查看namespace library,它非常轻量级且易于实现。

      (function(){
         namespace("MyClass", MyPublic);
      
         function MyPublic(x){
           return x+1;
         }
      })();
      

      它也支持自动嵌套

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          如您所见,在 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/

          【讨论】:

            【解决方案7】:

            这是我使用的设计模式,它允许嵌套命名空间以及稍后添加到命名空间(甚至从单独的 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/

            【讨论】:

              【解决方案8】:
              (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)
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-03-30
                • 2011-07-22
                • 1970-01-01
                • 1970-01-01
                • 2010-10-27
                • 2018-07-13
                • 2013-03-05
                相关资源
                最近更新 更多