no-implicit-globals

不允许在全局作用域内声明

最好的做法是避免 ‘polluting’ 全局作用域内的变量是脚本局部的。

¥It is the best practice to avoid ‘polluting’ the global scope with variables that are intended to be local to the script.

从脚本创建的全局变量可能会与从另一个脚本创建的全局变量产生名称冲突,这通常会导致运行时错误或意外行为。

¥Global variables created from a script can produce name collisions with global variables created from another script, which will usually lead to runtime errors or unexpected behavior.

此规则不允许以下内容:

¥This rule disallows the following:

  • 在全局作用域内创建一个或多个变量的声明。

    ¥Declarations that create one or more variables in the global scope.

  • 全局变量泄漏。

    ¥Global variable leaks.

  • 只读全局变量的重新声明和对只读全局变量的赋值。

    ¥Redeclarations of read-only global variables and assignments to read-only global variables.

有一种明确的方法可以在需要时通过分配给全局对象的属性来创建全局变量。

¥There is an explicit way to create a global variable when needed, by assigning to a property of the global object.

此规则对浏览器脚本最有用。ES 模块和 CommonJS 模块中的顶层声明创建模块作用域的变量。ES 模块也有隐式的 strict 模式,可以防止全局变量泄漏。

¥This rule is mostly useful for browser scripts. Top-level declarations in ES modules and CommonJS modules create module-scoped variables. ES modules also have implicit strict mode, which prevents global variable leaks.

默认情况下,此规则不检查 constletclass 声明。

¥By default, this rule does not check const, let and class declarations.

此规则有一个带有一个选项的对象选项:

¥This rule has an object option with one option:

  • 如果你希望此规则也检查 constletclass 声明,请将 "lexicalBindings" 设置为 true

    ¥Set "lexicalBindings" to true if you want this rule to check const, let and class declarations as well.

规则详情

¥Rule Details

varfunction 声明

¥var and function declarations

在使用浏览器脚本时,开发者经常忘记顶层作用域中的变量和函数声明成为 window 对象上的全局变量。与具有自己范围的模块相反。如果这是意图,则应将全局变量显式分配给 windowself。否则,打算在脚本中使用的变量应该包含在 IIFE 中。

¥When working with browser scripts, developers often forget that variable and function declarations at the top-level scope become global variables on the window object. As opposed to modules which have their own scope. Globals should be explicitly assigned to window or self if that is the intent. Otherwise variables intended to be local to the script should be wrapped in an IIFE.

此规则不允许在顶层脚本范围内声明 varfunction。这不适用于 ES 和 CommonJS 模块,因为它们具有模块作用域。

¥This rule disallows var and function declarations at the top-level script scope. This does not apply to ES and CommonJS modules since they have a module scope.

此规则的错误代码示例:

¥Examples of incorrect code for this rule:

在线运行
/*eslint no-implicit-globals: "error"*/

var foo = 1;

function bar() {}

此规则的正确代码示例:

¥Examples of correct code for this rule:

在线运行
/*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" } 的此规则的正确代码示例:

¥Examples of correct code for this rule with "parserOptions": { "sourceType": "module" } in the ESLint configuration:

在线运行
/*eslint no-implicit-globals: "error"*/

// foo and bar are local to module
var foo = 1;
function bar() {}

全局变量泄漏

¥Global variable leaks

当代码不处于 strict 模式时,对未声明变量的赋值会创建一个新的全局变量。即使代码在函数中也会发生这种情况。

¥When the code is not in strict mode, an assignment to an undeclared variable creates a new global variable. This will happen even if the code is in a function.

这不适用于 ES 模块,因为模块代码隐含在 strict 模式下。

¥This does not apply to ES modules since the module code is implicitly in strict mode.

此规则的错误代码示例:

¥Examples of incorrect code for this rule:

在线运行
/*eslint no-implicit-globals: "error"*/

foo = 1;

Bar.prototype.baz = function () {
    a = 1; // Intended to be this.a = 1;
};

只读全局变量

¥Read-only global variables

此规则还禁止重新声明只读全局变量和分配给只读全局变量。

¥This rule also disallows redeclarations of read-only global variables and assignments to read-only global variables.

只读全局变量可以是内置的 ES 全局变量(例如 Array),环境特定的全局变量(例如浏览器环境中的 window),或者在配置文件或 /*global */ 注释中定义为 readonly 的全局变量。

¥A read-only global variable can be a built-in ES global (e.g. Array), an environment specific global (e.g. window in the browser environment), or a global variable defined as readonly in the configuration file or in a /*global */ comment.

此规则的错误代码示例:

¥Examples of incorrect code for this rule:

在线运行
/*eslint no-implicit-globals: "error"*/

/*global foo:readonly*/

foo = 1;

Array = [];
var Object;

constletclass 声明

¥const, let and class declarations

词法声明 constlet 以及 class 声明创建了块作用域的变量。

¥Lexical declarations const and let, as well as class declarations, create variables that are block-scoped.

但是,当在浏览器脚本的顶层声明时,这些变量不是 ‘script-scoped’。它们实际上是在全局作用域内创建的,并且可能与 varconstlet 变量以及来自其他脚本的 functionclass 声明产生名称冲突。这不适用于 ES 和 CommonJS 模块。

¥However, when declared in the top-level of a browser script these variables are not ‘script-scoped’. They are actually created in the global scope and could produce name collisions with var, const and let variables and function and class declarations from other scripts. This does not apply to ES and CommonJS modules.

如果该变量是脚本的局部变量,请使用块或立即调用的函数表达式 (IIFE) 封装代码。

¥If the variable is intended to be local to the script, wrap the code with a block or with an immediately-invoked function expression (IIFE).

此规则的正确代码示例,其中 "lexicalBindings" 选项设置为 false(默认):

¥Examples of correct code for this rule with "lexicalBindings" option set to false (default):

在线运行
/*eslint no-implicit-globals: ["error", {"lexicalBindings": false}]*/

const foo = 1;

let baz;

class Bar {}

此规则的错误代码示例("lexicalBindings" 选项设置为 true):

¥Examples of incorrect code for this rule with "lexicalBindings" option set to true:

在线运行
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/

const foo = 1;

let baz;

class Bar {}

此规则的正确代码示例("lexicalBindings" 选项设置为 true):

¥Examples of correct code for this rule with "lexicalBindings" option set to true:

在线运行
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/

{
    const foo = 1;
    let baz;
    class Bar {}
}

(function() {
    const foo = 1;
    let baz;
    class Bar {}
}());

如果你打算创建一个全局 constlet 变量或全局 class 声明,以便在其他脚本中使用,请注意与传统方法(即 var 声明和分配给全局属性)相比存在某些差异 window 对象:

¥If you intend to create a global const or let variable or a global class declaration, to be used from other scripts, be aware that there are certain differences when compared to the traditional methods, which are var declarations and assigning to a property of the global window object:

  • 不能有条件地创建词法声明的变量。脚本无法检查变量是否存在,然后创建一个新变量。var 变量也总是被创建,但重新声明不会导致运行时异常。

    ¥Lexically declared variables cannot be conditionally created. A script cannot check for the existence of a variable and then create a new one. var variables are also always created, but redeclarations do not cause runtime exceptions.

  • 词法声明的变量不会在全局对象上创建属性,这是消费脚本可能期望的。

    ¥Lexically declared variables do not create properties on the global object, which is what a consuming script might expect.

  • 词法声明的变量是全局对象的隐藏属性,如果使用脚本同时使用变量和属性,则可能会产生错误。

    ¥Lexically declared variables are shadowing properties of the global object, which might produce errors if a consuming script is using both the variable and the property.

  • 如果初始化引发异常,词法声明的变量会产生永久的时间死区 (TDZ)。即使是 typeof 检查也不能避免 TDZ 引用异常。

    ¥Lexically declared variables can produce a permanent Temporal Dead Zone (TDZ) if the initialization throws an exception. Even the typeof check is not safe from TDZ reference exceptions.

此规则的错误代码示例("lexicalBindings" 选项设置为 true):

¥Examples of incorrect code for this rule with "lexicalBindings" option set to true:

在线运行
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/

const MyGlobalFunction = (function() {
    const a = 1;
    let b = 2;
    return function() {
        return a + b;
    }
}());

此规则的正确代码示例("lexicalBindings" 选项设置为 true):

¥Examples of correct code for this rule with "lexicalBindings" option set to 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 导出部分

¥You can use /* exported variableName */ block comments in the same way as in no-unused-vars. See the no-unused-vars exported section for details.

/* exported variableName */ 操作的正确代码示例:

¥Examples of correct code for /* exported variableName */ operation:

在线运行
/* eslint no-implicit-globals: error */
/* exported global_var */

var global_var = 42;

何时不使用

¥When Not To Use It

对于浏览器脚本,如果你希望能够在全局作用域内显式声明变量和函数,并且你的代码处于严格模式,或者你不希望此规则警告你未声明的变量,并且你还不希望此规则警告你有关只读全局变量的信息,你可以禁用此规则。

¥In the case of a browser script, if you want to be able to explicitly declare variables and functions in the global scope, and your code is in strict mode or you don’t want this rule to warn you about undeclared variables, and you also don’t want this rule to warn you about read-only globals, you can disable this rule.

对于 CommonJS 模块,如果你的代码处于严格模式,或者你不希望此规则警告你未声明的变量,并且你也不希望此规则警告你有关只读全局变量,你可以禁用此规则。

¥In the case of a CommonJS module, if your code is in strict mode or you don’t want this rule to warn you about undeclared variables, and you also don’t want this rule to warn you about the read-only globals, you can disable this rule.

对于 ES 模块,如果你不希望此规则警告你有关只读全局变量的信息,你可以禁用此规则。

¥In the case of an ES module, if you don’t want this rule to warn you about the read-only globals you can disable this rule.

版本

此规则是在 ESLint v2.0.0-alpha-1 中引入。

进阶读物

资源