no-unused-expressions
禁止未使用的表达式
对程序状态没有影响的未使用表达式表示逻辑错误。
🌐 An unused expression which has no effect on the state of the program indicates a logic error.
例如,n + 1; 不是语法错误,但它可能是一个打字错误,程序员原本想写一个赋值语句 n += 1;。有时,这些未使用的表达式可能会被某些构建工具在生产环境中删除,这可能会破坏应用逻辑。
🌐 For example, n + 1; is not a syntax error, but it might be a typing mistake where a programmer meant an assignment statement n += 1; instead. Sometimes, such unused expressions may be eliminated by some build tools in production environment, which possibly breaks application logic.
规则详情
🌐 Rule Details
该规则旨在消除对程序状态没有影响的未使用表达式。
🌐 This rule aims to eliminate unused expressions which have no effect on the state of the program.
这个规则不适用于带有 new 运算符的函数调用或构造函数调用,因为它们可能对程序的状态产生副作用。
🌐 This rule does not apply to function calls or constructor calls with the new operator, because they could have side effects on the state of the program.
let i = 0;
function increment() { i += 1; }
increment(); // return value is unused, but i changed as a side effect
let nThings = 0;
function Thing() { nThings += 1; }
new Thing(); // constructed object is unused, but nThings changed as a side effect
当在 ES5+ 环境中使用时,该规则不适用于指令(其形式为字面字符串表达式,例如在脚本、模块或函数开头的 "use strict";)。在 ES3 环境中,指令默认被视为未使用的表达式,但可以使用 ignoreDirectives 选项更改此行为。
🌐 This rule does not apply to directives (which are in the form of literal string expressions such as "use strict"; at the beginning of a script, module, or function) when using ES5+ environments. In ES3 environments, directives are treated as unused expressions by default, but this behavior can be changed using the ignoreDirectives option.
序列表达式(使用逗号的表达式,例如 a = 1, b = 2)除非其返回值被赋值或用于条件评估,或者使用序列表达式的值进行函数调用,否则总是被视为未使用。
🌐 Sequence expressions (those using a comma, such as a = 1, b = 2) are always considered unused unless their return value is assigned or used in a condition evaluation, or a function call is made with the sequence expression value.
选项
🌐 Options
此规则在默认状态下不需要任何参数。如果你想启用以下一项或多项,你可以传递一个对象,并按如下方式设置选项:
🌐 This rule, in its default state, does not require any arguments. If you would like to enable one or more of the following you may pass an object with the options set as follows:
allowShortCircuit设置为true将允许你在表达式中使用短路求值(默认值:false)。allowTernary设置为true将允许你在表达式中使用三元运算符,类似于短路求值(默认值:false)。allowTaggedTemplates设置为true将使你能够在表达式中使用带标签的模板字面量(默认值:false)。enforceForJSX设置为true将标记未使用的 JSX 元素表达式(默认值:false)。ignoreDirectives设置为true将防止在使用ecmaVersion: 3进行代码检查时将指令报告为未使用的表达式(默认值:false)。
这些选项只允许未使用的表达式,前提是所有代码路径要么直接改变状态(例如,赋值语句),要么可能有副作用(例如,函数调用)。
🌐 These options allow unused expressions only if all of the code paths either directly change the state (for example, assignment statement) or could have side effects (for example, function call).
默认 { "allowShortCircuit": false, "allowTernary": false } 选项的错误代码示例:
🌐 Examples of incorrect code for the default { "allowShortCircuit": false, "allowTernary": false } options:
/*eslint no-unused-expressions: "error"*/
0
if(0) 0
{0}
f(0), {}
a && b()
a, b()
c = a, b;
a() && function namedFunctionInExpressionContext () {f();}
(function anIncompleteIIFE () {});
injectGlobal`body{ color: red; }`
默认 { "allowShortCircuit": false, "allowTernary": false } 选项的正确代码示例:
🌐 Examples of correct code for the default { "allowShortCircuit": false, "allowTernary": false } options:
/*eslint no-unused-expressions: "error"*/
{} // In this context, this is a block statement, not an object literal
{ myLabel: foo() } // In this context, this is a block statement with a label and expression, not an object literal
function namedFunctionDeclaration () {}
(function aGenuineIIFE () {}());
f()
a = 0
new C
delete a.b
void a
请注意,一个或多个字符串表达式语句(无论是否带分号)只有在它们不位于脚本、模块或函数的开头(独自存在且未被其他语句打断)时,才会被视为未使用。否则,它们将被视为“指令序言”的一部分,这是 JavaScript 引擎可能使用的一个部分。这包括“严格模式”指令。
🌐 Note that one or more string expression statements (with or without semi-colons) will only be considered as unused if they are not in the beginning of a script, module, or function (alone and uninterrupted by other statements). Otherwise, they will be treated as part of a “directive prologue”, a section potentially usable by JavaScript engines. This includes “strict mode” directives.
关于指令,这条规则的正确代码示例:
🌐 Examples of correct code for this rule in regard to directives:
/*eslint no-unused-expressions: "error"*/
"use strict";
"use asm"
"use stricter";
"use babel"
"any other strings like this in the directive prologue";
"this is still the directive prologue";
function foo() {
"bar";
}
class Foo {
someMethod() {
"use strict";
}
}
关于指令,这条规则的错误代码示例:
🌐 Examples of incorrect code for this rule in regard to directives:
/*eslint no-unused-expressions: "error"*/
doSomething();
"use strict"; // this isn't in a directive prologue, because there is a non-directive statement before it
function foo() {
"bar" + 1;
}
class Foo {
static {
"use strict"; // class static blocks do not have directive prologues
}
}
allowShortCircuit
针对 { "allowShortCircuit": true } 选项的错误代码示例:
🌐 Examples of incorrect code for the { "allowShortCircuit": true } option:
/*eslint no-unused-expressions: ["error", { "allowShortCircuit": true }]*/
a || b
适用于 { "allowShortCircuit": true } 选项的正确代码示例:
🌐 Examples of correct code for the { "allowShortCircuit": true } option:
/*eslint no-unused-expressions: ["error", { "allowShortCircuit": true }]*/
a && b()
a() || (b = c)
allowTernary
针对 { "allowTernary": true } 选项的错误代码示例:
🌐 Examples of incorrect code for the { "allowTernary": true } option:
/*eslint no-unused-expressions: ["error", { "allowTernary": true }]*/
a ? b : 0
a ? b : c()
适用于 { "allowTernary": true } 选项的正确代码示例:
🌐 Examples of correct code for the { "allowTernary": true } option:
/*eslint no-unused-expressions: ["error", { "allowTernary": true }]*/
a ? b() : c()
a ? (b = c) : d()
allowShortCircuit 和 allowTernary
🌐 allowShortCircuit and allowTernary
适用于 { "allowShortCircuit": true, "allowTernary": true } 选项的正确代码示例:
🌐 Examples of correct code for the { "allowShortCircuit": true, "allowTernary": true } options:
/*eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }]*/
a ? b() || (c = d) : e()
allowTaggedTemplates
针对 { "allowTaggedTemplates": true } 选项的错误代码示例:
🌐 Examples of incorrect code for the { "allowTaggedTemplates": true } option:
/*eslint no-unused-expressions: ["error", { "allowTaggedTemplates": true }]*/
`some untagged template string`;
适用于 { "allowTaggedTemplates": true } 选项的正确代码示例:
🌐 Examples of correct code for the { "allowTaggedTemplates": true } option:
/*eslint no-unused-expressions: ["error", { "allowTaggedTemplates": true }]*/
tag`some tagged template string`;
enforceForJSX
JSX 最常用于 React 生态系统中,在那里它被编译为 React.createElement 表达式。虽然这些调用没有副作用,但 no-unused-expression 规则不会自动标记它们。如果你使用 React,或任何其他无副作用的 JSX 指令,可以启用此选项来标记这些表达式。
🌐 JSX is most-commonly used in the React ecosystem, where it is compiled to React.createElement expressions. Though free from side-effects, these calls are not automatically flagged by the no-unused-expression rule. If you’re using React, or any other side-effect-free JSX pragma, this option can be enabled to flag these expressions.
针对 { "enforceForJSX": true } 选项的错误代码示例:
🌐 Examples of incorrect code for the { "enforceForJSX": true } option:
/*eslint no-unused-expressions: ["error", { "enforceForJSX": true }]*/
<MyComponent />;
<></>;
适用于 { "enforceForJSX": true } 选项的正确代码示例:
🌐 Examples of correct code for the { "enforceForJSX": true } option:
/*eslint no-unused-expressions: ["error", { "enforceForJSX": true }]*/
const myComponentPartial = <MyComponent />;
const myFragment = <></>;
ignoreDirectives
当设置为 false(默认值)时,该规则在使用 ecmaVersion: 3 进行代码检查时,会将指令(如 "use strict")报告为未使用的表达式。这个默认行为存在的原因是 ES3 环境不正式支持指令,这意味着在特定上下文中,这些字符串实际上是未使用的表达式。
🌐 When set to false (default), this rule reports directives (like "use strict") as unused expressions when linting with ecmaVersion: 3. This default behavior exists because ES3 environments do not formally support directives, meaning such strings are effectively unused expressions in that specific context.
将此选项设置为 true 以防止指令被报告为未使用,即使指定了 ecmaVersion: 3。此选项主要适用于需要维护包含指令的单一代码库,同时支持旧的 ES3 环境和现代(ES5+)环境的项目。
🌐 Set this option to true to prevent directives from being reported as unused, even when ecmaVersion: 3 is specified. This option is primarily useful for projects that need to maintain a single codebase containing directives while supporting both older ES3 environments and modern (ES5+) environments.
注意: 在 ES5 及更高版本环境中,无论此设置如何,指令始终会被忽略。
{ “ignoreDirectives”: false } 选项和 ecmaVersion: 3 的错误代码示例:
🌐 Examples of incorrect code for the { "ignoreDirectives": false } option and ecmaVersion: 3:
/*eslint no-unused-expressions: ["error", { "ignoreDirectives": false }]*/
"use strict";
"use asm"
"use stricter";
"use babel"
"any other strings like this in the directive prologue";
"this is still the directive prologue";
function foo() {
"bar";
}
{ “ignoreDirectives”: true } 选项和 ecmaVersion: 3 的正确代码示例:
🌐 Examples of correct code for the { "ignoreDirectives": true } option and ecmaVersion: 3:
/*eslint no-unused-expressions: ["error", { "ignoreDirectives": true }]*/
"use strict";
"use asm"
"use stricter";
"use babel"
"any other strings like this in the directive prologue";
"this is still the directive prologue";
function foo() {
"bar";
}
TypeScript 支持
🌐 TypeScript Support
此规则支持 TypeScript 特定的表达式,并遵循以下准则:
🌐 This rule supports TypeScript-specific expressions and follows these guidelines:
- 指令(如
'use strict')允许在模块和命名空间声明中使用 - 如果类型相关的表达式的封装值表达式未使用,则将其视为未使用:
- 类型断言(
x as number、<number>x) - 非空断言(
x!) - 类型实例化(
Set<number>)
- 类型断言(
注意:虽然类型表达式在运行时从不产生副作用(例如,x! 在运行时等同于 x),但它们可以用于断言类型以进行测试。
在使用 TypeScript 时,该规则的正确代码示例:
🌐 Examples of correct code for this rule when using TypeScript:
/* eslint no-unused-expressions: "error" */
// Type expressions wrapping function calls are allowed
function getSet() {
return Set;
}
getSet()<number>;
getSet() as Set<unknown>;
getSet()!;
// Directives in modules and namespaces
module Foo {
'use strict';
'hello world';
}
namespace Bar {
'use strict';
export class Baz {}
}
在使用 TypeScript 时违反此规则的代码示例:
🌐 Examples of incorrect code for this rule when using TypeScript:
/* eslint no-unused-expressions: "error" */
// Standalone type expressions
Set<number>;
1 as number;
window!;
// Expressions inside namespaces
namespace Bar {
123;
}
版本
此规则是在 ESLint v0.1.0 中引入。