为什么 TypeScript 编译器通过两次检查来编译其可选链接和空合并运算符?

dx_*_*_dt 62 language-design typescript

为什么 TypeScript 编译器将其可选链接和空合并运算符以及?.,??编译为

// x?.y
x === null || x === void 0 ? void 0 : x.y;

// x ?? y
x !== null && x !== void 0 ? x : y
Run Code Online (Sandbox Code Playgroud)

代替

// x?.y
x == null ? void 0 : x.y

// x ?? y
x != null ? x : y
Run Code Online (Sandbox Code Playgroud)

很可能在幕后== null执行相同的两项检查,但即使出于代码长度的考虑,单次检查似乎会更干净。当使用可选链接字符串时,它也会添加更少的括号。

顺便说一句,我也很惊讶可选链不能编译为

x == null ? x : x.y
Run Code Online (Sandbox Code Playgroud)

保存nullvs undefined. 这个问题已经得到解答:为什么 JavaScript 的可选链要使用 undefined 而不是保留 null?

jca*_*alz 79

你可以在microsoft/TypeScript#16中找到权威答案(哇,老答案了);此评论中对此进行了具体解释:

这是因为document.all[...],为了向后兼容,语言中对此进行了特殊处理。

document.all == null // true
document.all === null || document.all === undefined // false
Run Code Online (Sandbox Code Playgroud)

在可选链提案中

document.all?.foo === document.all.foo
Run Code Online (Sandbox Code Playgroud)

document.all == null ? void 0 : document.all.foo会错误地返回void 0

因此,有一种特殊的、已弃用的、过时的、古怪的遗留伪属性边缘情况HTMLAllCollection,没有人使用,它松散地等于null但不严格等于undefinednull。惊人的!

似乎没有人认真考虑过破坏事物document.all。由于该xxx === null || xxx === undefined版本适用于所有情况,因此它可能是发出符合规范的向后兼容 JS 代码的最简洁方式。

  • 很好的 JavaScript。正是学习这样的东西让我感觉JS还是和PHP一样尴尬。我想知道我们是否会得到一个“使用严格的 20XX”来取消所有长期弃用的功能。 (6认同)
  • 顺便说一句,在 Babel 中,有一个 [“noDocumentAll” 假设](https://babeljs.io/docs/en/asminations#nodocumentall),您可以启用它以使其输出更简洁的版本。我不认为 TS 目前有同等的设置。 (3认同)