no-implicit-globals
禁止在全局作用域中声明
最佳实践是避免用旨在对脚本局部有效的变量“污染”全局作用域。
从脚本创建的全局变量会与从另一个脚本创建的全局变量产生名称冲突,这通常会导致运行时错误或意外行为。
此规则禁止以下操作
- 在全局作用域中创建一个或多个变量的声明。
- 全局变量泄漏。
- 重新声明只读全局变量和对只读全局变量的赋值。
有一种明确的方法可以在需要时创建全局变量,方法是将值分配给全局对象的属性。
此规则主要适用于浏览器脚本。ES 模块和 CommonJS 模块中的顶层声明创建模块范围的变量。ES 模块还具有隐式strict
模式,这可以防止全局变量泄漏。
默认情况下,此规则不检查const
、let
和class
声明。
此规则具有一个带有单个选项的对象选项
- 如果您希望此规则也检查
const
、let
和class
声明,请将"lexicalBindings"
设置为true
。
规则详细信息
var
和function
声明
在处理浏览器脚本时,开发人员经常忘记顶层范围的变量和函数声明会成为window
对象上的全局变量。这与具有自己范围的模块相反。全局变量应该明确地分配给window
或self
(如果这是意图)。否则,旨在对脚本局部有效的变量应该包装在 IIFE 中。
此规则禁止在顶层脚本范围内进行var
和function
声明。这并不适用于 ES 和 CommonJS 模块,因为它们具有模块范围。
此规则的不正确代码示例
/*eslint no-implicit-globals: "error"*/
var ;
此规则的正确代码示例
/*eslint no-implicit-globals: "error"*/
// explicitly set on window
window.foo = 1;
window.bar = function() {};
// intended to be scope to this file
(function() {
var foo = 1;
function bar() {}
})();
此规则的正确代码示例,ESLint 配置中包含"parserOptions": { "sourceType": "module" }
/*eslint no-implicit-globals: "error"*/
// foo and bar are local to module
var foo = 1;
function bar() {}
全局变量泄漏
当代码不在strict
模式中时,对未声明变量的赋值会创建一个新的全局变量。即使代码位于函数中,也会发生这种情况。
这并不适用于 ES 模块,因为模块代码隐式地处于strict
模式。
此规则的不正确代码示例
/*eslint no-implicit-globals: "error"*/
;
Bar.prototype.baz = function () {
; // Intended to be this.a = 1;
};
只读全局变量
此规则还禁止重新声明只读全局变量和对只读全局变量的赋值。
只读全局变量可以是内置 ES 全局变量(例如Array
)、环境特定的全局变量(例如浏览器环境中的window
),或在配置文件或/*global */
注释中定义为readonly
的全局变量。
此规则的不正确代码示例
/*eslint no-implicit-globals: "error"*/
/*global foo:readonly*/
;
;
var ;
const
、let
和class
声明
词法声明const
和let
以及class
声明创建的是块范围的变量。
但是,当在浏览器脚本的顶层声明时,这些变量不是“脚本范围”的。它们实际上是在全局作用域中创建的,可能会与来自其他脚本的var
、const
和let
变量以及function
和class
声明产生名称冲突。这并不适用于 ES 和 CommonJS 模块。
如果变量旨在对脚本局部有效,请使用块或立即调用函数表达式(IIFE)包装代码。
此规则的正确代码示例,"lexicalBindings"
选项设置为false
(默认值)
/*eslint no-implicit-globals: ["error", {"lexicalBindings": false}]*/
const foo = 1;
let baz;
class Bar {}
此规则的不正确代码示例,"lexicalBindings"
选项设置为true
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/
const ;
let ;
此规则的正确代码示例,"lexicalBindings"
选项设置为true
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/
{
const foo = 1;
let baz;
class Bar {}
}
(function() {
const foo = 1;
let baz;
class Bar {}
}());
如果您打算创建一个全局const
或let
变量或全局class
声明,以便从其他脚本中使用,请注意,与传统方法相比存在一些差异,这些方法是var
声明和将值分配给全局window
对象的属性
- 词法声明的变量不能有条件地创建。脚本不能检查变量是否存在,然后创建一个新的变量。
var
变量始终创建,但重新声明不会导致运行时异常。 - 词法声明的变量不会在全局对象上创建属性,而这正是使用脚本可能期望的。
- 词法声明的变量会遮蔽全局对象的属性,如果使用脚本同时使用变量和属性,则可能会导致错误。
- 如果初始化抛出异常,词法声明的变量可能会产生永久的暂时性死区(TDZ)。即使
typeof
检查也不能避免 TDZ 引用异常。
此规则的不正确代码示例,"lexicalBindings"
选项设置为true
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/
const ;
此规则的正确代码示例,"lexicalBindings"
选项设置为true
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/
window.MyGlobalFunction = (function() {
const a = 1;
let b = 2;
return function() {
return a + b;
}
}());
导出
您可以像在no-unused-vars
中一样使用/* exported variableName */
块注释。有关详细信息,请参见no-unused-vars
导出部分。
/* exported variableName */
操作的正确代码示例
/* eslint no-implicit-globals: error */
/* exported global_var */
var global_var = 42;
何时不使用它
对于浏览器脚本,如果您想能够在全局范围内显式声明变量和函数,并且您的代码处于严格模式,或者您不希望此规则警告您有关未声明的变量,并且您也不希望此规则警告您有关只读全局变量,您可以禁用此规则。
对于 CommonJS 模块,如果您的代码处于严格模式,或者您不希望此规则警告您有关未声明的变量,并且您也不希望此规则警告您有关只读全局变量,您可以禁用此规则。
对于 ES 模块,如果您不希望此规则警告您有关只读全局变量,您可以禁用此规则。
相关规则
版本
此规则在 ESLint v2.0.0-alpha-1 中引入。