语法错误:不能在 `||` 和 `&&` 表达式中使用不带括号的 `??`

空值合并运算符 在不带括号的同一表达式中与 逻辑或逻辑与 一起使用时,会出现 JavaScript 异常“不能在 ||&& 表达式中使用不带括号的 ??”。

¥The JavaScript exception "cannot use ?? unparenthesized within || and && expressions" occurs when an nullish coalescing operator is used with a logical OR or logical AND in the same expression without parentheses.

信息

¥Message

SyntaxError: Unexpected token '??' (V8-based)
SyntaxError: cannot use `??` unparenthesized within `||` and `&&` expressions (Firefox)
SyntaxError: Unexpected token '??'. Coalescing and logical operators used together in the same expression; parentheses must be used to disambiguate. (Safari)

错误类型

¥Error type

SyntaxError

什么地方出了错?

¥What went wrong?

运算符优先级 链如下所示:

¥The operator precedence chain looks like this:

|   >   &&   >   ||   >   =
|   >   ??   >   =

但是,故意未定义 ??&&/|| 之间的优先级,因为逻辑运算符的短路行为可能会使表达式的计算违反直觉。因此,以下组合都是语法错误,因为语言不知道如何给操作数加上括号:

¥However, the precedence between ?? and &&/|| is intentionally undefined, because the short circuiting behavior of logical operators can make the expression's evaluation counter-intuitive. Therefore, the following combinations are all syntax errors, because the language doesn't know how to parenthesize the operands:

js
a ?? b || c;
a || b ?? c;
a ?? b && c;
a && b ?? c;

相反,通过明确地在任一侧加上括号来明确你的意图:

¥Instead, make your intent clear by parenthesizing either side explicitly:

js
(a ?? b) || c;
a ?? (b && c);

示例

¥Examples

当迁移使用 ||&& 来防御 nullundefined 的旧代码时,你通常可能会对其进行部分转换:

¥When migrating legacy code that uses || and && for guarding against null or undefined, you may often convert it partially:

js
function getId(user, fallback) {
  // Previously: user && user.id || fallback
  return user && user.id ?? fallback; // SyntaxError: cannot use `??` unparenthesized within `||` and `&&` expressions
}

相反,请考虑将 && 添加括号:

¥Instead, consider parenthesizing the &&:

js
function getId(user, fallback) {
  return (user && user.id) ?? fallback;
}

更好的是,考虑使用 可选链接 而不是 &&

¥Even better, consider using optional chaining instead of &&:

js
function getId(user, fallback) {
  return user?.id ?? fallback;
}

也可以看看