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