我应该如何定义JavaScript'命名空间'来满足JSLint?

Mat*_*och 20 javascript namespaces jslint

我希望能够将我的JavaScript代码打包到"命名空间"中,以防止与其他库发生名称冲突.由于命名空间的声明应该是一段简单的代码,我不希望依赖任何外部库来为我提供此功能.我已经找到了关于如何简单地执行此操作的各种建议,但在通过JSLint运行时(使用"好的部件"选项)似乎没有任何错误.

作为一个例子,我尝试使用高级JavaScript(没有YUI的命名空间部分):

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}
Run Code Online (Sandbox Code Playgroud)

通过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
Run Code Online (Sandbox Code Playgroud)

可以通过明确声明来修复"隐含的全局"错误MyNamespace...

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    var MyNamespace = {};
}
Run Code Online (Sandbox Code Playgroud)

...并且可以通过在if块之外声明变量来修复其他两个错误.

"use strict";
var MyNamespace;
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}
Run Code Online (Sandbox Code Playgroud)

这样可行,但在我看来(因为MyNamespace在检查时它总是未定义?)它相当于更简单:

"use strict";
var MyNamespace = {};
Run Code Online (Sandbox Code Playgroud)

JSLint对此很满意,但我担心我已经将代码简化到了一定程度,以至于它将不再能够正确地作为命名空间运行.这个最终的配方是否合理?

bob*_*nce 18

不要把JSLint的话当作福音.它说的大部分内容都是明智的,但它也伴随着很多Crockford的个人教条.特别是我并不总是同意他最好的地方var.

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}
Run Code Online (Sandbox Code Playgroud)

那个人不好; 抱怨隐含的全局,JSLint是正确的.'use strict'要求你不要暗示全局.

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    var MyNamespace = {};
}
Run Code Online (Sandbox Code Playgroud)

没关系.所述var悬挂所以MyNamespace是存在并设置为undefined在进入代码块.因此,(MyNamespace===undefined)即使没有typeof操作员的神奇能力,您也可以进行测试,以便让您引用不存在的变量.

另一种方法是使用明确的in运算符(这是区分存在但设置为的缺失属性的唯一方法undefined).对于普通浏览器脚本中的全局变量,可以将其用于全局window对象:

'use strict';
if (!('MyNamespace' in window)) {
    window.MyNamespace = {};
}
Run Code Online (Sandbox Code Playgroud)

(JSLint也不喜欢这样,因为'假设一个浏览器'似乎没有定义window出一些不可思议的原因.嘿嘿.)

  • 没关系,只要我们确实在谈论全球代码.如果声明一个已经有值的全局`var`,则没有任何反应(它没有重置为`undefined`).而如果声明一个与定义的全局同名的本地`var`,则值为"undefined"的局部变量会隐藏全局变量. (2认同)

Rya*_*yan 7

您可以尝试更短的版本:

var MyNamespace = MyNamespace || {};
Run Code Online (Sandbox Code Playgroud)

这应该在JSLint中有效,即使在严格模式下,如果它已经存在则使用名称,如果不存在则创建它,因为JavaScript中的命名空间最好能够工作.

  • 即使将MyNamespace添加为全局predef,现在也会失败.报告的错误是"MyNamespace"超出范围. (2认同)

Idi*_*tic 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
Run Code Online (Sandbox Code Playgroud)

'这'是必要的,以避免超出范围的错误(似乎它应该无关紧要,但我想使用'this'是显而易见的,只使用ns或var ns两者都会抛出错误.

需要iffy模式以避免全局"use strict"错误

当然其他工具不喜欢'this'作为一个iffy param警告它是全局的(当然是故意的)所以...番茄番茄