JavaScript命名空间

时间:2010-08-05 00:49:31

标签: javascript design-patterns namespaces

我想为我的应用程序创建一个全局命名空间,在那个命名空间中我想要其他命名空间:

E.g。

Dashboard.Ajax.Post()

Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent();

我也想将它们放在单独的文件中:

  • Ajax.js
  • RetrieveContent.js

但是我尝试使用this方法,但是它不起作用,因为在2个单独的位置使用相同的变量名称作为命名空间。有人可以提供替代方案吗?

感谢。

11 个答案:

答案 0 :(得分:9)

如果已经创建了命名空间对象,您只需要确保不要踩踏它。像这样的东西会起作用:

(function() {
    // private vars can go in here


    Dashboard = Dashboard || {};
    Dashboard.Ajax = {
        Post: function() {
            ...
        }
    };
})();

RetrieveContent文件的定义类似。

答案 1 :(得分:7)

Here是关于JavaScript中各种“模块模式”的非常好的文章。关于如何扩充模块或命名空间以及维护跨文件私有状态,有一个非常好的小部分。也就是说,单独文件中的代码将按顺序执行,并在执行后正确扩充名称空间。

我没有彻底探索过这种技术,所以没有承诺......但这是基本的想法。

<强> dashboard.js

(function(window){

    var dashboard  = (function () { 
        var my = {}, 
            privateVariable = 1; 

        function privateMethod() { 
            // ... 
        } 

        my.moduleProperty = 1; 
        my.moduleMethod = function () { 
            // ... 
        }; 

        return my; 
    }());

    window.Dashboard = dashboard;
})(window);

<强> dashboard.ajax.js

var dashboard = (function (my) { 
    var _private = my._private = my._private || {}, 
        _seal = my._seal = my._seal || function () { 
            delete my._private; 
            delete my._seal; 
            delete my._unseal; 
        }, 
        _unseal = my._unseal = my._unseal || function () { 
            my._private = _private; 
            my._seal = _seal; 
            my._unseal = _unseal; 
        }; 

    // permanent access to _private, _seal, and _unseal

    my.ajax = function(){ 
        // ...
    }

    return my; 
}(dashboard || {}));

<强> dashboard.retrieveContent.js

var dashboard = (function (my) { 
    var _private = my._private = my._private || {}, 
        _seal = my._seal = my._seal || function () { 
            delete my._private; 
            delete my._seal; 
            delete my._unseal; 
        }, 
        _unseal = my._unseal = my._unseal || function () { 
            my._private = _private; 
            my._seal = _seal; 
            my._unseal = _unseal; 
        }; 

    // permanent access to _private, _seal, and _unseal

    my.retrieveContent = function(){ 
        // ...
    }

    return my; 
}(dashboard || {}));

答案 2 :(得分:4)

Yahoo Namespace功能完全针对此问题而设计。

添加了:

该功能的source可用。如果需要,您可以将其复制到您自己的代码中,将根目录从YAHOO更改为其他内容等等。

答案 3 :(得分:3)

如果您想使用或检查预先烘焙(即经过测试)的解决方案,有几个库已经提供了这种功能。

最简单且最无错误的可能是jQuery.extenddeep参数设置为true。 (我说它没有错误的原因不是因为我认为jQuery.extend比其他任何库都有更少的错误 - 但是因为它提供了从发送者到接收者的深度复制属性的明确选项 - - 大多数其他库显式都没有提供。这将防止许多难以诊断的错误在您的程序中出现,因为您使用了浅拷贝extend而现在函数在你不期望它们执行的上下文中执行。(但是如果你知道在设计方法时如何扩展基础库,这应该不是问题。)

答案 4 :(得分:3)

创建NS对象后,您应该可以从任何地方添加它。虽然您可能想尝试var NS = NS || {};以确保NS对象存在且不被覆盖。

// NS is a global variable for a namespace for the app's code
var NS = NS || {};

NS.Obj = (function() {

  // Private vars and methods always available to returned object via closure
  var foo; // ...

  // Methods in here are public
  return {
    method: function() {

    }
  };

}());

答案 5 :(得分:1)

你可以这样做......

使用命名空间库的HTML页面:

<html>
<head>
    <title>javascript namespacing</title>
    <script src="dashboard.js" type="text/javascript"></script>
    <script src="ajax.js" type="text/javascript"></script>
    <script src="retrieve_content.js" type="text/javascript"></script>
    <script type="text/javascript">
        alert(Dashboard.Ajax.Post());
        alert(Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent());
        Dashboard.RetrieveContent.Settings.Timeout = 1500;
        alert(Dashboard.RetrieveContent.Settings.Timeout);
    </script>
</head>

<body>
    whatever...
</body>

</html>

<强> Dashboard.js:

(function(window, undefined){
    var dashboard = {};
    window.Dashboard = dashboard;
})(window);

<强> Ajax.js:

(function(){
    var ajax = {};
    ajax.Post = function() { return "Posted!" };
    window.Dashboard.Ajax = ajax
})();

<强> Retrieve_Content.js:

(function(){
    var retrieveContent = {};
    retrieveContent.RefreshSalespersonPerformanceContent = function() { 
        return "content retrieved"
    };


    var _contentType;
    var _timeout;
    retrieveContent.Settings = {
        "ContentType": function(contentType) { _contentType = contentType; },
        "ContentType": function() { return _contentType; },
        "Timeout": function(timeout) { _timeout = timeout; },
        "Timeout": function() { return _timeout; }
    };

    window.Dashboard.RetrieveContent = retrieveContent;

})();

Dashboard.js充当其下所有命名空间的起点。其余的在各自的文件中定义。在Retrieve_Content.js中,我在Settings下添加了一些额外的属性,以便在需要时了解如何执行此操作。

答案 6 :(得分:1)

我相信模块模式可能就在你的小巷里。这是一篇关于不同模块模式的好文章。

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

答案 7 :(得分:1)

我强烈建议你使用这种技术:

https://github.com/mckoss/namespace

  namespace.lookup('com.mydomain.mymodule').define(function (ns) {
  var external = namespace.lookup('com.domain.external-module');

  function myFunction() {
    ...
  }

  ...

  ns.extend({
    'myFunction': myFunction,
     ...
  });
});

我一直在使用这种模式几年;我希望更多的图书馆能做同样的事情;这让我更容易在不同的项目中共享代码。

答案 8 :(得分:1)

我写了这个函数来简化创建命名空间。 Mabey它会帮助你。

function ns(nsstr) {
    var t = nsstr.split('.');
    var obj = window[t[0]] = window[t[0]] || {};
    for (var i = 1; i < t.length; i++) {
        obj[t[i]] = obj[t[i]] || {};
        obj = obj[t[i]];
    }
}

ns('mynamespace.isawesome.andgreat.andstuff');
mynamespace.isawesome.andgreat.andstuff = 3;

console.log(mynamespace.isawesome.andgreat.andstuff);

答案 9 :(得分:0)

bob.js可以帮助您定义命名空间(以及其他):

bob.ns.setNs('Dashboard.Ajax', {

    Post: function () { /*...*/ }
});

bob.ns.setNs('Dashboard.RetrieveContent', {

    RefreshSalespersonPerformanceContent: function () { /*...*/ }
});

答案 10 :(得分:0)

<强>实施

namespace = function(packageName)
{
    // Local variables.
    var layers, layer, currentLayer, i;

    // Split the given string into an array.
    // Each element represents a namespace layer.
    layers = packageName.split('.');

    // If the top layer does not exist in the global namespace.
    if (eval("typeof " + layers[0]) === 'undefined')
    {
        // Define the top layer in the global namesapce.
        eval(layers[0] + " = {};");
    }

    // Assign the top layer to 'currentLayer'.
    eval("currentLayer = " + layers[0] + ";");

    for (i = 1; i < layers.length; ++i)
    {
        // A layer name.
        layer = layers[i];

        // If the layer does not exist under the current layer.
        if (!(layer in currentLayer))
        {
            // Add the layer under the current layer.
            currentLayer[layer] = {};
        }

        // Down to the next layer.
        currentLayer = currentLayer[layer];
    }

    // Return the hash object that represents the last layer.
    return currentLayer;
};


结果:

namespace('Dashboard.Ajax').Post = function() {
    ......
};

namespace('Dashboard.RetrieveContent').RefreshSalespersonPerformanceContent = function() {
    ......
};


要点:

namespace.js