我希望能够将我的JavaScript代码打包成'命名空间',以防止与其他库发生名称冲突。由于命名空间的声明应该是一段简单的代码,因此我不想依赖任何外部库来为我提供此功能。我已经找到了关于如何简单地执行此操作的各种建议,但在JSLint(使用“好的部件”选项)时,似乎没有任何错误。
作为一个例子,我在Advanced JavaScript(没有YUI的命名空间部分)中尝试了这个:
"use strict";
if (typeof(MyNamespace) === 'undefined') {
MyNamespace = {};
}
通过JSLint运行此操作会出现以下错误:
Problem at line 2 character 12: 'MyNamespace' is not defined.
Problem at line 3 character 5: 'MyNamespace' is not defined.
Implied global: MyNamespace 2,3
可以通过明确声明MyNamespace
...
"use strict";
if (typeof(MyNamespace) === 'undefined') {
var MyNamespace = {};
}
...并且可以通过在if块之外声明变量来修复其他两个错误。
"use strict";
var MyNamespace;
if (typeof(MyNamespace) === 'undefined') {
MyNamespace = {};
}
这样有效,但在我看来(因为MyNamespace
在检查时总是未定义?)它等同于更简单:
"use strict";
var MyNamespace = {};
JSLint对此感到满意,但我担心我已经将代码简化到一定程度,以至于它将不再能够正确地作为命名空间运行。这最终的配方是否合理?
答案 0 :(得分:18)
不要把JSLint的话当作福音。它说的大部分内容都是明智的,但它也伴随着很多Crockford的个人教条。特别是我并不总是同意他关于var
的最佳位置。
"use strict";
if (typeof(MyNamespace) === 'undefined') {
MyNamespace = {};
}
那个人不好;抱怨隐含的全局,JSLint是正确的。 'use strict'
要求你不要暗示全局。
"use strict";
if (typeof(MyNamespace) === 'undefined') {
var MyNamespace = {};
}
没关系。 var
已提升,因此MyNamespace
存在,并在进入代码块时设置为undefined
。因此,即使没有(MyNamespace===undefined)
运算符的神奇功能,您也可以使用typeof
进行测试,以便让您引用不存在的变量。
另一种方法是使用明确的in
运算符(这是区分缺席属性但存在但设置为undefined
的唯一方法)。对于普通浏览器脚本中的全局变量,可以将其用于全局window
对象:
'use strict';
if (!('MyNamespace' in window)) {
window.MyNamespace = {};
}
(JSLint也不喜欢这样,因为'假设一个浏览器'似乎没有定义window
因为某些不可思议的原因。嘿嘿。)
答案 1 :(得分:7)
您可以尝试更短的版本:
var MyNamespace = MyNamespace || {};
这在JSLint中应该是有效的,即使在严格模式下,如果它已经存在则使用该名称,如果不存在则创建它,因为JavaScript中的命名空间最好能够工作。
答案 2 :(得分:6)
这是一个非常古老的问题,但我认为无论如何我都会回答,因为以上都没有清除jslint的所有错误因为我怀疑lint'r已更新:-)
可能有其他方法可以做到这一点,但截至2013年,这是我能提出的最佳方法
如果你想要一个带有命名空间的错误的jsLint模块模式,严格看下面的
假设这包含在某些.js文件中......
this.ns = this.ns || {}; // Check for global namespace and if not found create
(function(ns) {
'use strict' // restrict usage to this module
ns.myFunction = function() {
}
} (this.ns)); // Pass in the global namespace you 'might' have created above and
// drop 'this' reference
'this'是必要的,以避免超出范围的错误(似乎它应该无关紧要,但我想使用'this'是明确的,只使用ns或var ns两者都会抛出错误。
需要iffy模式以避免全局'use strict'错误
当然其他工具不喜欢'this'作为一个iffy param警告它是全局的(当然是故意的)所以...番茄番茄
答案 3 :(得分:3)
您可以通过window["NAMEOFGLOBAL"]
语法访问全局变量,因此您可以像这样进行检查:
if(typeof(window['MyNamespace']) === 'undefined') {
答案 4 :(得分:1)
当然,未定义检查的目的是确保用户不会双重加载或覆盖现有命名空间。因此,我认为你走得太远了。
怎么样:
var MyNs;
if(MyNs==null){
//foo()
}
答案 5 :(得分:1)
之前我遇到过这个问题。你肯定不想使用你的最终形式,因为它完全绕过对已定义变量的检查,并且总是会将其覆盖为空对象,即使事物已经存储在其中。
我认为你的倒数第二种形式最适合创建命名空间,但实际上第一种形式也是不错的。在我看来,JSLint报告的错误类似于catch-22s并没有太多担心。我认为放弃声明并不是什么大不了的原因是,在以前的某个点加载命名空间 的情况下,你最终会得到JSLint的“变量在它之前被使用”被定义为“错误,所以你基本上只是为另一个警告交易。