我被告知不应使用命名空间,因为它们会“污染”全局范围。我想知道有什么替代方案?
当我想为网站定义实用程序函数和/或常量时,一种简单的方法是通过命名空间定义它们,这样对全局范围的损害仅限于一个对象。
如果命名空间是不好的做法,那么会想到几个问题:
- 为什么这是不好的做法?
- 该声明的范围是什么(网络应用程序/动态网站/静态网站等)?
- 有哪些替代方案?
这个问题是在一篇关于使用 extend.js 的好处的帖子上开始讨论的结果。
我被告知不应使用命名空间,因为它们会“污染”全局范围。我想知道有什么替代方案?
当我想为网站定义实用程序函数和/或常量时,一种简单的方法是通过命名空间定义它们,这样对全局范围的损害仅限于一个对象。
如果命名空间是不好的做法,那么会想到几个问题:
这个问题是在一篇关于使用 extend.js 的好处的帖子上开始讨论的结果。
为什么这是不好的做法?
命名空间本身很糟糕,因为它是一个不必要的概念。
拥有具有属性和方法的对象是可以接受的。拥有一个类似于“命名空间”的“模块”令牌也很好,但其含义是每个文件都有一个“模块”令牌,其中包含所有属性和方法。这与“命名空间”不同,因为它仅在单个文件中创建/更改,并且不作为全局令牌公开。
该声明的范围是什么(网络应用程序/动态网站/静态网站等)?
所有 ECMAScript,从不创建新的全局令牌
有哪些选择?
而不是拥有命名空间,您应该支持多个“文件本地”令牌。这意味着每个文件/“模块”都应该包装在一个闭包中,并且您应该可以访问这个闭包内的多个局部变量。
全局变量也很糟糕,因为你根本不需要它们。避免全局变量的方法是将所有内容包装在闭包中,并在加载外部 javascript 文件的方式上保持智能。
零全局模块加载器示例
进一步阅读:
我无法想象为什么命名空间会是一件坏事。除非有一些我不知道的特定于 JavaScript 的命名空间定义。
我目前正在开发一个小型库,所有内容都包含在一个顶级对象(命名空间?)中。我没有在窗口或内在类型上放任何东西;如果您需要我的图书馆中的某些东西,它可以在kilo
对象中找到。
对我来说,拥有这个“命名空间”是一种很好的做法,因为它可以让我很快知道我是否正在调用库中的方法。无需重写window.alert
可能与页面上加载的另一个库发生冲突的方法;仅kilo.alert
用于自定义版本(这是一个人为的示例,但我希望它能够说明问题)。
我个人认为那些说你不应该污染全球范围的人没有正确定义“污染”。例如,您可以在某种程度上在本机Math
对象中看到这一点。我知道的所有其他编程语言都将所有数学函数都作为普通函数,但 JS 没有。但是,如果您将其发挥到极致,core.dialog.alert
例如,可以使用一个简单的警报框。
我喜欢将我所有的代码封闭在闭包中,以保持变量干净。但是,我的主 JS 脚本文件在全局范围内定义了一堆实用函数,例如自定义Alert()
、或AJAX()
或其他广泛使用的函数。如果我要经常使用它们,我不想用命名空间调用来膨胀文件。而且由于我在闭包中定义了所有变量,因此不会有意外覆盖函数的风险(我可能会在闭包本身中这样做,但它对全局范围没有影响)。
总的来说,命名空间被高估了。只需编写您的代码,不要为每个window
属性哭泣。
JavaScript 中的“命名空间”实际上只是具有命名属性的对象。在其他 OO 语言(即 C++、C# 等)中,我认为您不需要以下内容:
C# -
public static class MyAppName {}
public static class MyArea {}
public static class MySubArea {}
public static class Test {
public string Property1 { get { return "test"; }}
}
只是这样你就可以拥有
MyAppName.MyArea.MySubArea.Test.Property1;
所以基本上,因为 JS 实际上并不支持命名空间,所以人们发明了一种 hack 来模拟命名空间,这使得编写如下内容变得“酷”:
myAppSpace.mySubArea.myObject = blah...