版本

no-inner-declarations

禁止在嵌套块中声明变量或function

在 JavaScript 中,ES6 之前,函数声明只能在程序的第一级或另一个函数的主体中使用,尽管解析器有时会错误地接受它们出现在其他地方。这仅适用于函数声明;命名或匿名的函数表达式可以在任何允许表达式的任何位置出现。

// 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

变量声明允许在任何语句可以出现的地方,甚至嵌套在其他块的深处。由于变量提升,这通常是不希望的,将声明移动到程序或函数主体根部可以提高清晰度。请注意,块绑定letconst)不会提升,因此不受此规则影响。

// 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"选项时,此规则的错误代码示例

在游乐场中打开
/*eslint no-inner-declarations: "error"*/

// script, non-strict code

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

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

if (foo) function f(){}

使用默认"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) {
    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"选项时,此规则的正确代码示例

在游乐场中打开
/*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() { }
}

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

// strict code

function foo() {
    "use strict";

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

使用{ 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 中引入的。

资源

更改语言