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 中引入。