如何在JavaScript中创建命名空间,使我的对象和函数不被其他同名对象和函数覆盖?我使用了以下方法:

if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}

有没有更优雅或更简洁的方式来做到这一点?


当前回答

我最近最喜欢的图案是这样的:

Var命名空间=(函数(){ //暴露给公众 返回{ internalA, c: internalC } //所有私有 /** *完整的JSDoc * / 函数internalA() { / /…… } /** *完整的JSDoc * / 函数internalB() { / /…… } /** *完整的JSDoc * / 函数internalC() { / /…… } /** *完整的JSDoc * / 函数internalD() { / /…… } }) ();

当然,return可以在后面,但是如果后面只有函数声明,那么就更容易看到名称空间是关于什么的,以及暴露了什么API。

在这种情况下使用函数表达式的模式导致不遍历整个代码就无法知道公开了哪些方法。

其他回答

因为您可能会编写不同的JavaScript文件,然后在应用程序中组合或不组合它们,所以每个文件都需要能够恢复或构造名称空间对象,而不会破坏其他文件的工作……

一个文件可能打算使用命名空间namespace.namespace1:

namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};

namespace.namespace1.doSomeThing = function(){}

另一个文件可能想要使用命名空间namespace2:

namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};

namespace.namespace2.doSomeThing = function(){}

这两个文件可以共存,也可以分开而不会发生碰撞。

我喜欢这个:

var yourNamespace = {

    foo: function() {
    },

    bar: function() {
    }
};

...

yourNamespace.foo();

JavaScript默认情况下不支持命名空间。因此,如果您创建任何元素(函数、方法、对象、变量),那么它将变成全局的,并污染全局命名空间。让我们以定义两个没有任何名称空间的函数为例,

function func1() {
    console.log("This is a first definition");

}
function func1() {
    console.log("This is a second definition");
}
func1(); // This is a second definition

它总是调用第二个函数定义。在这种情况下,命名空间将解决名称冲突问题。

我使用在企业jQuery网站上找到的方法:

下面是他们的例子,展示了如何声明私有和公共属性和函数。一切都是作为一个自动执行的匿名函数完成的。

(function( skillet, $, undefined ) {
    //Private Property
    var isHot = true;

    //Public Property
    skillet.ingredient = "Bacon Strips";

    //Public Method
    skillet.fry = function() {
        var oliveOil;

        addItem( "\t\n Butter \n\t" );
        addItem( oliveOil );
        console.log( "Frying " + skillet.ingredient );
    };

    //Private Method
    function addItem( item ) {
        if ( item !== undefined ) {
            console.log( "Adding " + $.trim(item) );
        }
    }
}( window.skillet = window.skillet || {}, jQuery ));

如果你想访问某个公共成员你只需输入skillet。fry()或skillet。配料。

真正酷的是,现在可以使用完全相同的语法扩展名称空间。

//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
    //Private Property
    var amountOfGrease = "1 Cup";

    //Public Method
    skillet.toString = function() {
        console.log( skillet.quantity + " " +
                     skillet.ingredient + " & " +
                     amountOfGrease + " of Grease" );
        console.log( isHot ? "Hot" : "Cold" );
    };
}( window.skillet = window.skillet || {}, jQuery ));

第三个未定义的参数

The third, undefined argument is the source of the variable of value undefined. I'm not sure if it's still relevant today, but while working with older browsers / JavaScript standards (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variable undefined is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable named undefined which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the value undefined.

在将我的几个库移植到不同的项目中,并且不得不不断更改顶级(静态命名的)名称空间之后,我转而使用这个小的(开源的)帮助函数来定义名称空间。

global_namespace.Define('startpad.base', function(ns) {
    var Other = ns.Import('startpad.other');
    ....
});

关于好处的描述在我的博客文章中。您可以在这里获取源代码。

我非常喜欢的一个好处是模块之间相对于加载顺序的隔离。你可以在加载外部模块之前引用它。当代码可用时,将填充您获得的对象引用。