Javascript命名空间 - 这是一个好模式吗?

时间:2011-03-08 10:18:42

标签: javascript namespaces javascript-namespaces

...目标

  1. 从全局对象中删除变量,对象等。
  2. 消除碰撞的可能性。
  3. 首先,我实现了Yahoo命名空间代码(注意例如,我使用ROOT作为命名空间的根目录)...

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

    现在我宣布我的第一个命名空间......

    ROOT.namespace("UI");
    
                ROOT.UI = {
                    utc: 12345,
                    getUtc: function() {
                        return this.utc;
                    }
                }
    

    我想在这里做的是为我的UI保存我需要的变量(在这种情况下是UTC的当前时间),以便它们不在全局对象上。我还想提供一些特定的功能。这应该在每个页面上都可用,没有任何形式的实现...

    现在我希望在我的命名空间结构中存储一个对象。但是,需要多次创建此对象。这里的目标是将其保留在我的结构中,但允许它根据我的需要多次创建。具体如下:

     ROOT.namespace("AirportFinder");
                ROOT.AirportFinder = function(){ 
                    this.var1 = 99999;
    
                    this.Display = function() {
                        alert(this.var1);
                    }            
                }
    

    这是实例化对象的示例代码......

            var test1 = new ROOT.AirportFinder();
            test1.Display();
    

    这是一个好模式吗?

4 个答案:

答案 0 :(得分:1)

在命名空间ROOT或类似的东西上定义事物确实是合理的。

使用闭包也更好

(function() {
    var AirportFinder = function() { 
        this.var1 = 99999;
        this.Display = function() {
            alert(this.var1);
        }            
    };

    // do Stuff with local AirportFinder here.

    // If neccesary hoist to global namespace
    ROOT.AirportFinder = AirportFinder;
}());

如果他们不需要是全球性的。我自己使用别名($.foobar因为jQuery是全局的)来存储任何全局数据。

恐怕我不能告诉你.namespace函数的作用。这不是必要的。

我个人的偏好是始终使用闭包来创建私有命名空间,并将任何内容提升到必要的全局/共享命名空间。这会将全局可见性/群集降至最低。

答案 1 :(得分:0)

稍微指着你一点,离开问题的路径: 看看YUI3(http://developer.yahoo.com/yui/3/) - 你没有(有)任何东西在那里的全局命名空间,你得到一个私人沙箱。伟大的概念,我喜欢那个图书馆和它的conocepts(YUI3,不是在谈论旧的YUI2)。它的方式当然很简单,你也可以这样做:YUI3的动态模块加载器加载你的模块(.js文件),创建一个沙箱(只是一个闭包)并调用你的回调,给它一个处理沙箱。任何地方都没有其他代码可以访问该沙箱和您自己的名称。在该沙箱中,您可以(并且应该)继续使用各种封装模式。这个YUI3概念非常适合具有外部代码的mashup,特别是当mashup本质上变得更具动态性(例如用户触发)时,而不是仅仅由程序员自己集成Google Maps或其他众所周知的API。

答案 2 :(得分:0)

我试着做类似的事情:

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/

答案 3 :(得分:0)

通过使用匿名自执行功能,您可以允许公共和私有属性/方法。

这是我最喜欢的模式:

(function ($, MyObject, undefined) {
  MyObject.publicFunction = function() {
      console.log("This is a public function!");
  };
  var privateFunction = function() {
    console.log("This is a private function!");
  };

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

  // You can even nest the namespaces
  MyObject.nestedNamespace = MyObject.nestedNamespace || {};      
  MyObject.nestedNamespace.logNestedMessage = function () {    
     console.log("Nested!!");
  };

}(jQuery, window.MyObject = window.MyObject || {}));

MyObject.sayStuff();
MyObject.nestedNamespace.logNestedMessage();
MyObject.publicFunction();

this article的评论中了解到这一点。