no-inner-declarations

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

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

¥In JavaScript, prior to ES6, a function declaration is only allowed in the first level of a program or the body of another function, though parsers sometimes erroneously accept them elsewhere. This only applies to function declarations; named or anonymous function expressions can occur anywhere an expression is permitted.

// 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 模块)。在非严格模式下,可以在块作用域之外访问和调用它们。

¥In ES6, block-level functions (functions declared inside a block) are limited to the scope of the block they are declared in and outside of the block scope they can’t be accessed and called, but only when the code is in strict mode (code with "use strict" tag or ESM modules). In non-strict mode, they can be accessed and called outside of the block scope.

"use strict";

if (test) {
    function doSomething () { }

    doSomething(); // no error
}

doSomething(); // error

变量声明可以在语句可以到达的任何地方进行,甚至可以嵌套在其他块的深处。由于变量提升,这通常是不可取的,并且将声明移动到程序或函数体的根可以增加清晰度。请注意,块绑定 (let, const) 没有被吊起,因此它们不受此规则的影响。

¥A variable declaration is permitted anywhere a statement can go, even nested deeply inside other blocks. This is often undesirable due to variable hoisting, and moving declarations to the root of the program or function body can increase clarity. Note that block bindings (let, const) are not hoisted and therefore they are not affected by this rule.

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

规则详情

¥Rule Details

该规则要求函数声明和变量声明(可选)位于程序的根目录中,或位于函数主体的根目录中,或位于类静态块主体的根目录中。

¥This rule requires that function declarations and, optionally, variable declarations be in the root of a program, or in the root of the body of a function, or in the root of the body of a class static block.

选项

¥Options

该规则有一个字符串和一个对象选项:

¥This rule has a string and an object option:

  • "functions"(默认)不允许在嵌套块中声明 function

    ¥"functions" (default) disallows function declarations in nested blocks

  • "both" 不允许在嵌套块中声明 functionvar

    ¥"both" disallows function and var declarations in nested blocks

  • { blockScopedFunctions: "allow" }(默认)当代码处于严格模式(带有 "use strict" 标记或 ESM 模块的代码)并且 languageOptions.ecmaVersion 设置为 2015 或更高时,此选项允许在嵌套块中声明 function。可以通过将其设置为 "disallow" 来禁用此选项。

    ¥{ blockScopedFunctions: "allow" } (default) this option allows function declarations in nested blocks when code is in strict mode (code with "use strict" tag or ESM modules) and languageOptions.ecmaVersion is set to 2015 or above. This option can be disabled by setting it to "disallow".

functions

使用默认 "functions" 选项的此规则的错误代码示例:

¥Examples of incorrect code for this rule with the default "functions" option:

在线运行
/*eslint no-inner-declarations: "error"*/

// script, non-strict code

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

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

if (foo) function f(){}

使用默认 "functions" 选项的此规则的正确代码示例:

¥Examples of correct code for this rule with the default "functions" option:

在线运行
/*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" 选项的此规则的错误代码示例:

¥Examples of incorrect code for this rule with the "both" option:

在线运行
/*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" 选项的此规则的正确代码示例:

¥Examples of correct code for this rule with the "both" option:

在线运行
/*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):

¥Example of incorrect code for this rule with { blockScopedFunctions: "disallow" } option with 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):

¥Example of correct code for this rule with { blockScopedFunctions: "disallow" } option with ecmaVersion: 2015:

在线运行
/*eslint no-inner-declarations: ["error", "functions", { blockScopedFunctions: "disallow" }]*/

function doSomething() { }

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

此规则的正确代码示例(带有 { blockScopedFunctions: "allow" } 选项和 ecmaVersion: 2015):

¥Example of correct code for this rule with { blockScopedFunctions: "allow" } option with 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 modulesclass 声明和表达式始终处于严格模式。

¥ESM modules and both class declarations and expressions are always in strict mode.

在线运行
/*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() { }
        }
    }
}

何时不使用

¥When Not To Use It

默认情况下,此规则仅在其行为未指定并因此不一致(ES6 之前的环境)或旧语义适用(非严格模式代码)的上下文中不允许内部函数声明。如果你的代码针对 ES6 之前的环境或未处于严格模式,则应启用此规则以防止意外行为。

¥By default, this rule disallows inner function declarations only in contexts where their behavior is unspecified and thus inconsistent (pre-ES6 environments) or legacy semantics apply (non-strict mode code). If your code targets pre-ES6 environments or is not in strict mode, you should enable this rule to prevent unexpected behavior.

在 ES6+ 环境中,在严格模式代码中,内部函数声明的行为是定义良好且一致的 - 它们始终是块作用域的。如果你的代码仅针对 ES6+ 环境并且处于严格模式(ES 模块或带有 "use strict" 指令的代码),则无需启用此规则,除非你希望禁止内部函数作为风格选择,在这种情况下你应该启用此规则 使用选项 blockScopedFunctions: "disallow" 进行规则。

¥In ES6+ environments, in strict mode code, the behavior of inner function declarations is well-defined and consistent - they are always block-scoped. If your code targets only ES6+ environments and is in strict mode (ES modules, or code with "use strict" directives) then there is no need to enable this rule unless you want to disallow inner functions as a stylistic choice, in which case you should enable this rule with the option blockScopedFunctions: "disallow".

在使用 block-scoped-var 时禁用检查变量声明,或者在嵌套块中声明变量是否可以接受,尽管有提升。

¥Disable checking variable declarations when using block-scoped-var or if declaring variables in nested blocks is acceptable despite hoisting.

版本

此规则是在 ESLint v0.6.0 中引入。

资源

ESLint 中文网
粤ICP备13048890号