版本

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" 不允許在巢狀區塊中進行 functionvar 宣告
  • { blockScopedFunctions: "allow" }(預設)此選項允許當程式碼處於嚴格模式(具有 "use strict" 標籤或 ESM 模組的程式碼)且 languageOptions.ecmaVersion 設定為 2015 或更高版本時,在巢狀區塊中進行 function 宣告。可以將其設定為 "disallow" 以停用此選項。

functions

使用預設的 "functions" 選項時,此規則的不正確程式碼範例

在 Playground 中開啟
/*eslint no-inner-declarations: "error"*/

// script, non-strict code

if (test) {
    function doSomething() { }
}

function doSomethingElse() {
    if (test) {
        function doAnotherThing() { }
    }
}

if (foo) function f(){}

使用預設的 "functions" 選項時,此規則的正確程式碼範例

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

在 Playground 中開啟
/*eslint no-inner-declarations: ["error", "both"]*/

if (test) {
    var foo = 42;
}

function doAnotherThing() {
    if (test) {
        var bar = 81;
    }
}

if (foo) var a;

if (foo) function f(){}

class C {
    static {
        if (test) {
            var something;
        }
    }
}

使用 "both" 選項時,此規則的正確程式碼範例

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

在 Playground 中開啟
/*eslint no-inner-declarations: ["error", "functions", { blockScopedFunctions: "disallow" }]*/

// non-strict code

if (test) {
    function doSomething() { }
}

function doSomething() {
    if (test) {
        function doSomethingElse() { }
    }
}

// strict code

function foo() {
    "use strict";

    if (test) {
        function bar() { }
    }
}

使用 { blockScopedFunctions: "disallow" } 選項且 ecmaVersion: 2015 時,此規則的正確程式碼範例

在 Playground 中開啟
/*eslint no-inner-declarations: ["error", "functions", { blockScopedFunctions: "disallow" }]*/

function doSomething() { }

function doSomething() {
    function doSomethingElse() { }
}

使用 { blockScopedFunctions: "allow" } 選項且 ecmaVersion: 2015 時,此規則的正確程式碼範例

在 Playground 中開啟
/*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 宣告和表達式始終處於嚴格模式。

在 Playground 中開啟
/*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 中引入。

資源

變更語言