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
),或是設定檔或 /*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 中引入。
延伸閱讀

