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 中引入。