版本

no-implicit-globals

禁止在全局作用域中声明变量

最佳实践是避免使用旨在作为脚本局部变量的变量“污染”全局作用域。

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

此规则禁止以下操作

  • 在全局作用域中创建一个或多个变量的声明。
  • 全局变量泄漏。
  • 重新声明只读全局变量以及对只读全局变量的赋值。

在需要时,有一种显式的方法来创建全局变量,即为全局对象的属性赋值。

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

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

此规则具有一个包含一个选项的对象选项

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

规则详情

varfunction 声明

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

此规则禁止在顶层脚本作用域中使用varfunction声明。这并不适用于 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;

constletclass声明

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

但是,当在浏览器脚本的顶层声明时,这些变量不是“脚本作用域”的。它们实际上是在全局作用域中创建的,并且可能与来自其他脚本的varconstlet变量以及functionclass声明发生名称冲突。这并不适用于 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 {}
}());

如果您打算创建一个全局constlet变量或一个全局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;
    }
}());

导出

您可以像在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 中引入。

进一步阅读

资源

更改语言