no-inner-declarations
不允許在巢狀區塊中使用變數或 function
宣告
在 ES6 之前的 JavaScript 中,函數宣告僅允許在程式的第一層或另一個函數的主體中,儘管解析器有時會錯誤地在其他地方接受它們。這僅適用於函數宣告;具名或匿名函數表達式可以出現在任何允許表達式的地方。
// Good
function doSomething() { }
// Bad
if (test) {
function doSomethingElse () { }
}
function anotherThing() {
var fn;
if (test) {
// Good
fn = function expression() { };
// Bad
function declaration() { }
}
}
在 ES6 中,區塊層級函數(在區塊內宣告的函數)僅限於宣告它們的區塊範圍,並且在區塊範圍之外無法存取和呼叫它們,但僅當程式碼處於嚴格模式時(帶有 "use strict"
標籤或 ESM 模組的程式碼)。在非嚴格模式下,它們可以在區塊範圍之外存取和呼叫。
"use strict";
if (test) {
function doSomething () { }
doSomething(); // no error
}
doSomething(); // error
變數宣告允許在任何可以放置陳述式的地方,甚至深深地巢狀在其他區塊內。由於變數提升,這通常是不希望發生的,將宣告移動到程式或函數主體的根目錄可以提高清晰度。請注意,區塊綁定(let
、const
)不會被提升,因此它們不受此規則的影響。
// Good
var foo = 42;
// Good
if (foo) {
let bar1;
}
// Bad
while (test) {
var bar2;
}
function doSomething() {
// Good
var baz = true;
// Bad
if (baz) {
var quux;
}
}
規則詳細資訊
此規則要求函數宣告以及可選的變數宣告必須位於程式的根目錄、函數主體的根目錄或類別靜態區塊的主體根目錄。
選項
此規則有一個字串和一個物件選項
"functions"
(預設)不允許在巢狀區塊中使用function
宣告"both"
不允許在巢狀區塊中使用function
和var
宣告{ blockScopedFunctions: "allow" }
(預設)此選項允許在程式碼處於嚴格模式時(帶有"use strict"
標籤或 ESM 模組)且languageOptions.ecmaVersion
設定為2015
或更高版本時,在巢狀區塊中使用function
宣告。可以透過將此選項設定為"disallow"
來停用此選項。
functions
對於使用預設 "functions"
選項的此規則,不正確程式碼的範例
/*eslint no-inner-declarations: "error"*/
// script, non-strict code
if (test) {
}
function doSomethingElse() {
if (test) {
}
}
if (foo)
對於使用預設 "functions"
選項的此規則,正確程式碼的範例
/*eslint no-inner-declarations: "error"*/
function doSomething() { }
function doSomethingElse() {
function doAnotherThing() { }
}
function doSomethingElse() {
"use strict";
if (test) {
function doAnotherThing() { }
}
}
class C {
static {
function doSomething() { }
}
}
if (test) {
asyncCall(id, function (err, data) { });
}
var fn;
if (test) {
fn = function fnExpression() { };
}
if (foo) var a;
both
對於使用 "both"
選項的此規則,不正確程式碼的範例
/*eslint no-inner-declarations: ["error", "both"]*/
if (test) {
}
function doAnotherThing() {
if (test) {
}
}
if (foo)
if (foo)
class C {
static {
if (test) {
}
}
}
對於使用 "both"
選項的此規則,正確程式碼的範例
/*eslint no-inner-declarations: ["error", "both"]*/
var bar = 42;
if (test) {
let baz = 43;
}
function doAnotherThing() {
var baz = 81;
}
class C {
static {
var something;
}
}
blockScopedFunctions
對於使用 { blockScopedFunctions: "disallow" }
選項且 ecmaVersion: 2015
的此規則,不正確程式碼的範例
/*eslint no-inner-declarations: ["error", "functions", { blockScopedFunctions: "disallow" }]*/
// non-strict code
if (test) {
}
function doSomething() {
if (test) {
}
}
// strict code
function foo() {
"use strict";
if (test) {
}
}
對於使用 { blockScopedFunctions: "disallow" }
選項且 ecmaVersion: 2015
的此規則,正確程式碼的範例
/*eslint no-inner-declarations: ["error", "functions", { blockScopedFunctions: "disallow" }]*/
function doSomething() { }
function doSomething() {
function doSomethingElse() { }
}
對於使用 { blockScopedFunctions: "allow" }
選項且 ecmaVersion: 2015
的此規則,正確程式碼的範例
/*eslint no-inner-declarations: ["error", "functions", { blockScopedFunctions: "allow" }]*/
"use strict";
if (test) {
function doSomething() { }
}
function doSomething() {
if (test) {
function doSomethingElse() { }
}
}
// OR
function foo() {
"use strict";
if (test) {
function bar() { }
}
}
ESM 模組
以及 class
宣告和表達式始終處於嚴格模式。
/*eslint no-inner-declarations: ["error", "functions", { blockScopedFunctions: "allow" }]*/
if (test) {
function doSomething() { }
}
function doSomethingElse() {
if (test) {
function doAnotherThing() { }
}
}
class Some {
static {
if (test) {
function doSomething() { }
}
}
}
const C = class {
static {
if (test) {
function doSomething() { }
}
}
}
何時不該使用它
預設情況下,此規則僅在行為未指定且因此不一致(ES6 之前的環境)或應用傳統語意(非嚴格模式程式碼)的上下文中,不允許內部函數宣告。如果您的程式碼目標是 ES6 之前的環境或不是嚴格模式,您應該啟用此規則以防止意外行為。
在 ES6+ 環境中,在嚴格模式程式碼中,內部函數宣告的行為已明確定義且一致 - 它們始終是區塊作用域的。如果您的程式碼僅以 ES6+ 環境為目標並且處於嚴格模式(ES 模組或帶有 "use strict"
指令的程式碼),則無需啟用此規則,除非您想要作為一種風格選擇而不允許內部函數,在這種情況下,您應該使用選項 blockScopedFunctions: "disallow"
啟用此規則。
當使用 block-scoped-var 時,或如果儘管提升變數但在巢狀區塊中宣告變數是可以接受的,則停用檢查變數宣告。
版本
此規則在 ESLint v0.6.0 中引入。