版本

no-implicit-globals

不允許在全域作用域中宣告

最佳實務是避免使用腳本本機變數「污染」全域作用域。

從一個腳本建立的全域變數可能會與從另一個腳本建立的全域變數產生名稱衝突,這通常會導致執行階段錯誤或非預期的行為。

此規則不允許以下情況

  • 在全域作用域中建立一個或多個變數的宣告。
  • 全域變數洩漏。
  • 重新宣告唯讀全域變數以及賦值給唯讀全域變數。

當需要建立全域變數時,有一種明確的方法,即賦值給全域物件的屬性。

此規則主要適用於瀏覽器腳本。ES 模組和 CommonJS 模組中的頂層宣告會建立模組作用域變數。ES 模組也具有隱含的 strict 模式,可防止全域變數洩漏。

預設情況下,此規則不會檢查 constletclass 宣告。

此規則具有一個物件選項,其中包含一個選項

  • 如果您希望此規則也檢查 constletclass 宣告,請將 "lexicalBindings" 設定為 true

規則詳細資訊

varfunction 宣告

在使用瀏覽器腳本時,開發人員經常忘記頂層作用域中的變數和函數宣告會變成 window 物件上的全域變數。這與具有自身作用域的模組相反。如果這是意圖,則應將全域變數明確賦值給 windowself。否則,預期為腳本本機的變數應包裝在 IIFE 中。

此規則不允許在頂層腳本作用域中使用 varfunction 宣告。這不適用於 ES 和 CommonJS 模組,因為它們具有模組作用域。

此規則的錯誤程式碼範例

在 Playground 中開啟
/*eslint no-implicit-globals: "error"*/

var foo = 1;

function bar() {}

此規則的正確程式碼範例

在 Playground 中開啟
/*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" } 時,此規則的正確程式碼範例

在 Playground 中開啟
/*eslint no-implicit-globals: "error"*/

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

全域變數洩漏

當程式碼不在 strict 模式下時,賦值給未宣告的變數會建立新的全域變數。即使程式碼在函數中也會發生這種情況。

這不適用於 ES 模組,因為模組程式碼隱含地處於 strict 模式。

此規則的錯誤程式碼範例

在 Playground 中開啟
/*eslint no-implicit-globals: "error"*/

foo = 1;

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

唯讀全域變數

此規則也不允許重新宣告唯讀全域變數以及賦值給唯讀全域變數。

唯讀全域變數可以是內建的 ES 全域變數(例如 Array),或是設定檔或 /*global */ 註解中定義為 readonly 的全域變數。

另請參閱:指定全域變數

此規則的錯誤程式碼範例

在 Playground 中開啟
/*eslint no-implicit-globals: "error"*/

/*global foo:readonly*/

foo = 1;

Array = [];
var Object;

constletclass 宣告

詞法宣告 constlet,以及 class 宣告,會建立區塊作用域的變數。

但是,當在瀏覽器腳本的頂層宣告時,這些變數不是「腳本作用域」。它們實際上是在全域作用域中建立的,可能會與其他腳本中的 varconstlet 變數以及 functionclass 宣告產生名稱衝突。這不適用於 ES 和 CommonJS 模組。

如果變數預期為腳本本機變數,請使用區塊或立即調用函數表達式 (IIFE) 包裝程式碼。

"lexicalBindings" 選項設定為 false(預設值)時,此規則的正確程式碼範例

在 Playground 中開啟
/*eslint no-implicit-globals: ["error", {"lexicalBindings": false}]*/

const foo = 1;

let baz;

class Bar {}

"lexicalBindings" 選項設定為 true 時,此規則的錯誤程式碼範例

在 Playground 中開啟
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/

const foo = 1;

let baz;

class Bar {}

"lexicalBindings" 選項設定為 true 時,此規則的正確程式碼範例

在 Playground 中開啟
/*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 時,此規則的錯誤程式碼範例

在 Playground 中開啟
/*eslint no-implicit-globals: ["error", {"lexicalBindings": true}]*/

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

"lexicalBindings" 選項設定為 true 時,此規則的正確程式碼範例

在 Playground 中開啟
/*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 */ 操作的正確程式碼範例

在 Playground 中開啟
/* eslint no-implicit-globals: error */
/* exported global_var */

var global_var = 42;

何時不該使用

在瀏覽器腳本的情況下,如果您希望能夠明確地在全域作用域中宣告變數和函數,並且您的程式碼處於嚴格模式,或者您不希望此規則警告您有關未宣告的變數,並且您也不希望此規則警告您有關唯讀全域變數,則可以停用此規則。

在 CommonJS 模組的情況下,如果您的程式碼處於嚴格模式,或者您不希望此規則警告您有關未宣告的變數,並且您也不希望此規則警告您有關唯讀全域變數,則可以停用此規則。

在 ES 模組的情況下,如果您不希望此規則警告您有關唯讀全域變數,則可以停用此規則。

版本

此規則在 ESLint v2.0.0-alpha-1 中引入。

延伸閱讀

資源

變更語言