# no-implicit-globals
禁止在全局范围内声明
最好的做法是避免 'polluting' 全局范围内的变量是脚本本地的。
从脚本创建的全局变量可能会与从另一个脚本创建的全局变量产生名称冲突,这通常会导致运行时错误或意外行为。
此规则不允许以下内容:
- 在全局范围内创建一个或多个变量的声明。
- 全局变量泄漏。
- 只读全局变量的重新声明和对只读全局变量的赋值。
有一种明确的方法可以在需要时通过分配给全局对象的属性来创建全局变量。
此规则对浏览器脚本最有用。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 foo = 1;
function bar() {}
此规则的正确代码示例:
/*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"*/
foo = 1;
Bar.prototype.baz = function () {
a = 1; // Intended to be this.a = 1;
};
# 只读全局变量
此规则还禁止重新声明只读全局变量和分配给只读全局变量。
只读全局变量可以是内置的 ES 全局变量(例如 Array
),环境特定的全局变量(例如浏览器环境中的 window
),或者在配置文件或 /*global */
注释中定义为 readonly
的全局变量。
指定环境
指定全局变量
此规则的错误代码示例:
/*eslint no-implicit-globals: "error"*/
/*global foo:readonly*/
foo = 1;
Array = [];
var Object;
# const、let 和 class 声明
词法声明 const
和 let
以及 class
声明创建了块作用域的变量。
但是,当在浏览器脚本的顶层声明时,这些变量不是 'script-scoped'。它们实际上是在全局范围内创建的,并且可能与 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 foo = 1;
let baz;
class Bar {}
此规则的正确代码示例,其中 "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 MyGlobalFunction = (function() {
const a = 1;
let b = 2;
return function() {
return a + b;
}
}());
此规则的正确代码示例,其中 "lexicalBindings"
选项设置为 true
:
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/
window.MyGlobalFunction = (function() {
const a = 1;
let b = 2;
return function() {
return a + b;
}
}());
# exported
您可以像在 no-unused-vars
中一样使用 /* exported variableName */
块注释。有关详细信息,请参见 no-unused-vars 导出部分
。
/* exported variableName */
操作的正确代码示例:
/* exported global_var */
var global_var = 42;
# 何时不使用
对于浏览器脚本,如果您希望能够在全局范围内显式声明变量和函数,并且您的代码处于严格模式,或者您不希望此规则警告您未声明的变量,并且您还不希望此规则警告您有关只读全局变量的信息,您可以禁用此规则。
对于 CommonJS 模块,如果您的代码处于严格模式,或者您不希望此规则警告您未声明的变量,并且您也不希望此规则警告您有关只读全局变量,您可以禁用此规则。
对于 ES 模块,如果您不希望此规则警告您有关只读全局变量的信息,您可以禁用此规则。