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
变量声明允许在任何语句可以出现的地方,甚至嵌套在其他块的深处。由于变量提升,这通常是不希望的,将声明移动到程序或函数主体根部可以提高清晰度。请注意,块绑定(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 中引入的。