使用 JavaScript 命名空间是否存在任何危险?
创建 JavaScript 命名空间时是否应该注意任何危险/警告?
我们的项目相当庞大,我们正在运行大量 JavaScript 文件(超过 20 个,预计还会更多)。如果不使用命名空间,就不可能实现任何代码可维护性,因此我们像这样实现它们:
var namespace1 = {
doSomething: function() {
...
},
doSomethingElse: function() {
...
}
}
然后为了创建层次结构,我们像这样链接它们:
var globalNamespace = {
functions1: namespace1,
functions2: namespace2,
...
}
这工作正常,但本质上是一个“技巧”,使 JS 表现得像它确实有命名空间。尽管这种方法被广泛使用,但大多数文献似乎都关注如何做到这一点,而不是是否存在任何可能的缺点。随着我们编写越来越多的 JS 代码,它很快就会成为我们系统工作方式中不可或缺的一部分。因此,它的无缝运行非常重要。
在任何情况下,这种“诱导”的命名空间系统是否会导致您出错,或者需要特别注意?我们可以放心地期望所有浏览器都有相同的行为吗?
Are there any dangers/caveats one should be aware of when creating JavaScript namespaces?
Our project is fairly expansive and we are running a lot of JavaScript files (20+, expecting more). It is impossible to have any code maintainability without using namespaces, so we are implementing them like so:
var namespace1 = {
doSomething: function() {
...
},
doSomethingElse: function() {
...
}
}
And then to create hierarchies, we link them like so:
var globalNamespace = {
functions1: namespace1,
functions2: namespace2,
...
}
This works fine, but it is essentially a "trick" to make JS behave as if it did have namespaces. Although this method gets used a lot, most literature on this seems to focus on how to do it, and not whether there are any possible drawbacks. As we write more JS code, this is quickly becoming an integral part of the way our system works. So it's important that it works seamlessly.
Were there any situations in which this "induced" namespace system caused you errors, or otherwise needed special attention? Can we safely expect identical behaviour across all browsers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在示例中定义命名空间的方式似乎是在每个命名空间之外创建全局变量,因此最终会得到这样的结果。
因此,如果您有任何破坏
window.namespace1
的内容,它也会破坏window.globalNamespace。 namespace1
编辑:
这是我们解决这个问题的方法:
然后像这样使用它:
这样您就不必引入新的全局变量,并且可以放心地添加到现有命名空间,而不会破坏其他对象 它。
The way you define namespaces in your example it appears to create globals out of each namespace so you end up with
So if you have anything that clobbers
window.namespace1
it will also clobberwindow.globalNamespace.namespace1
edit:
Here's how we got around this problem:
Then you use it like this:
This way you don't have to introduce new global variables and you can confidently add to an existing namespace without clobbering other objects in it.
由于您基本上是将函数添加到对象并将这些对象添加到其他对象中,因此我希望每个浏览器都以相同的方式处理此问题。
但如果你想要模块化,为什么不使用像 require.js 这样的(相对)简单的框架呢?这将允许您和您的团队以模块化方式编写代码,并允许团队在需要时“导入”这些模块:
Require.js 将处理依赖关系,并且还将防止污染全局命名空间。
Since you are basically adding functions to objects and those objects into other objects, I would expect each browser to handle this the same way.
But if you want modularity, why not use a (relatively) simple framework like require.js? That will allow you and your team to write code in a modular fashion and allows the team to 'import' these modules where needed:
Require.js will take care of dependencies, and it will also prevent polluting the global namespace.
我们在工作中使用类似的系统,它的工作效果很好。我不认为有任何缺点;它只是对象和属性。出于同样的原因,跨浏览器兼容性应该很好。您最终可能需要编写一些长名称来解析为特定函数,例如 Foo.Bar.Test.Namespace2.Function,但即便如此,也可以通过预先将其分配给变量来解决。
We use a similar system at work and it does the job just fine. I don't see any drawbacks there could be; it's just objects and properties. For that same reason, cross browser compatibility should be good. You can end up having to write some long names to resolve to a particular function, like
Foo.Bar.Test.Namespace2.Function
, but even then that can be solved by assigning it to a variable before hand.这就是我建议这样做的方式,这样除了“基本”命名空间之外,您就完全脱离了全局范围。我们在我工作的地方也做了类似的事情。假设您在 Acme co 工作,并希望 ACME 作为您的基本命名空间。
在每个文件的顶部,您将包括:
然后您只需根据该文件定义您想要的任何内容即可。
如果您想要更深层次的命名空间,只需对每个级别执行相同的操作即可。
这样,每个文件都可以独立测试,并且它们将自动设置命名空间基础结构,但是当您将它们编译在一起或同时测试多个文件时,它们不会继续覆盖已经定义的内容。
This is how I'd recommend doing it, so you stay out of the global scope entirely except for your "base" namespace. We do something similar where I work. Let's say you work for Acme co, and want ACME to be your base namespace.
At the top of every file, you'd include:
Then you just go and define whatever you want in terms of that.
If you want a deeper level of namespace, you just do the same thing for each level.
This way each file can be tested independently and they'll set up the namespace infrastructure automatically, but when you compile them together or if you test multiple files simultaneously, they won't keep overwriting things that are already defined.