使用JavaScript命名空间有任何危险吗?

在创建JavaScript命名空间时,是否应该注意任何危险/警告?

我们的项目相当广泛,我们运行了很多JavaScript文件(20多个,期待更多)。 不使用命名空间就不可能有任何代码可维护性,所以我们这样实现它们:

var namespace1 = { doSomething: function() { ... }, doSomethingElse: function() { ... } } 

然后创建层次结构,我们将它们链接起来:

 var globalNamespace = { functions1: namespace1, functions2: namespace2, ... } 

这工作正常,但它本质上是一个“技巧”,使JS表现得好像它确实有名称空间。 虽然这种方法得到了很多使用,但大多数文献似乎都集中在如何做到这一点,而不是是否存在任何可能的缺点。 随着我们编写更多JS代码,这很快就会成为我们系统工作方式的一个组成部分。 因此,无缝工作非常重要。

是否存在这种“诱导”命名空间系统导致错误或需要特别注意的情况? 我们能安全地期望所有浏览器都有相同的行为

您在示例中定义名称空间的方式似乎是从每个名称空间中创建全局变量,因此您最终会使用

 window.namespace1 window.namespace2 window.globalNamespace window.globalNamespace.namespace1 window.globalNamespace.namespace2 

因此,如果你有任何破坏window.namespace1东西,它也会破坏window.globalNamespace.namespace1

编辑:

以下是我们解决这个问题的方法:

 namespacing = { init: function(namespace) { var spaces = []; namespace.split('.').each(function(space) { var curSpace = window, i; spaces.push(space); for (i = 0; i < spaces.length; i++) { if (typeof curSpace[spaces[i]] === 'undefined') { curSpace[spaces[i]] = {}; } curSpace = curSpace[spaces[i]]; } }); } }; 

然后你像这样使用它:

 namespacing.init('globalNamespace.namespace1'); globalNamespace.namespace1.doSomething = function() { ... }; 

这样您就不必引入新的全局变量,并且可以放心地添加到现有的命名空间而不会破坏其中的其他对象。

由于您基本上是将对象和这些对象的函数添加到其他对象中,我希望每个浏览器都以相同的方式处理它。

但是如果你想要模块化,为什么不使用像require.js这样的(相对)简单的框架呢? 这将允许您和您的团队以模块化方式编写代码,并允许团队在需要时“导入”这些模块:

 require(["helper/util"], function() { //This function is called when scripts/helper/util.js is loaded. }); 

Require.js将处理依赖关系,它还可以防止污染全局命名空间。

我们在工作中使用类似的系统,它可以很好地完成工作。 我没有看到任何可能的缺点; 它只是对象和属性。 出于同样的原因,跨浏览器兼容性应该是好的。 您最终可能需要编写一些长名称来解析特定函数,例如Foo.Bar.Test.Namespace2.Function ,但即便如此,也可以通过将其分配给变量来解决。

这就是我建议的方式,因此除了“基础”命名空间之外,你完全不在全局范围内。 我们在工作的地方做类似的事情。 假设您为Acme co工作,并希望ACME成为您的基本命名空间。

在每个文件的顶部,您将包括:

 if (!window.ACME) { window.ACME = {} } 

然后你就可以根据需要定义你想要的任何东西。

 ACME.Foo = { bar: function () { console.log("baz"); } } 

如果你想要更深层次的命名空间,你只需为每个级别做同样的事情。

 if (!window.ACME) { window.ACME = {} } if (!ACME.Foo) { ACME.Foo = {} } 

这样,每个文件都可以独立测试,并且它们将自动设置命名空间基础结构,但是当您一起编译它们或者同时测试多个文件时,它们将不会覆盖已定义的内容。