语法错误:new 关键字不能与可选的链

new 表达式的构造函数是 可选链 时,或者构造函数和括号中的参数列表之间存在可选链时,会发生 JavaScript 异常 "new 关键字不能与可选的链"。

¥The JavaScript exception "new keyword cannot be used with an optional chain" occurs when the constructor of a new expression is an optional chain, or if there's an optional chain between the constructor and the parenthesized list of arguments.

信息

¥Message

SyntaxError: Invalid optional chain from new expression (V8-based)
SyntaxError: new keyword cannot be used with an optional chain (Firefox)
SyntaxError: Cannot call constructor in an optional chain. (Safari)

错误类型

¥Error type

SyntaxError

什么地方出了错?

¥What went wrong?

有两种方法可以获取此错误。第一个是如果构造函数表达式是可选链表达式,如下所示:

¥There are two ways to get this error. The first one is if the constructor expression is an optional chain expression, like this:

js
new Intl?.DateTimeFormat();
Number?.[parseMethod]`Hello, world!`;

第二个是如果 ?. 出现在构造函数和参数列表之间,如下所示:

¥The second one is if ?. occurs between the constructor and the arguments list, like this:

js
new Intl.DateTimeFormat?.();

可选的 new 是特别禁止的,因为它的语法很复杂(new 有无参数),而且结果不明确(这是 new 不计算为对象值的唯一情况)。你需要将可选链接转换为其底层条件(有关更多信息,请参阅 可选链接)。

¥Optional new is specifically forbidden because its syntax is complicated (new with and without arguments), and the result is unclear (it would be the only case where new does not evaluate to an object value). You need to translate the optional chaining to its underlying condition (see optional chaining for more information).

js
const result =
  Intl.DateTimeFormat === null || Intl.DateTimeFormat === undefined
    ? undefined
    : new Intl.DateTimeFormat();

请记住,可选链接仅在带括号的单元内短路。如果将构造函数表达式括起来,则可选链不会导致错误,因为现在构造函数不会短路,结果很清楚(构造函数将生成 undefined,然后导致 new 表达式抛出)。

¥Remember that optional chaining only short-circuits within a parenthesized unit. If you parenthesize your constructor expression, the optional chaining will not cause an error, because now the constructor does not short-circuit and the result is clear (the constructor will produce undefined and then cause the new expression to throw).

js
new (Intl?.DateTimeFormat)(); // Throws if Intl?.DateTimeFormat is undefined

然而,这无论如何都有点荒谬,因为可选链可以防止属性访问链中出现错误,但保证在调用 new 时会产生错误。你可能仍想使用条件检查。

¥However this is a bit nonsensical anyway because optional chaining prevents errors inside the property access chain, but is then guaranteed to generate an error when calling new. You would probably still want to use a conditional check.

请注意,可选链接仅作为构造函数表达式被禁止。你可以在参数列表中使用可选链接,也可以在整个 new 表达式上使用可选链接。

¥Note that optional chaining is only forbidden as the constructor expression. You can use optional chaining inside the argument list, or use optional chaining on the new expression as a whole.

js
new Intl.DateTimeFormat(navigator?.languages);
new Intl.DateTimeFormat().resolvedOptions?.();

请注意,没有必要在 new 表达式本身上使用 ?.new a()?.b,因为 new 保证产生非空对象值。

¥Note that there's no needs to use ?. on the new expression itself: new a()?.b, because new is guaranteed to produce a non-nullish object value.

也可以看看