为什么 JavaScript 的可选链使用 undefined 而不是保留 null?

dx_*_*_dt 3 javascript language-design

这是我在《为什么 TypeScript 编译器通过两次检查来编译其可选链和空合并运算符?》末尾顺便问的一个后续问题。 正如 TypeScript 传奇人物jcalz在评论中指出的那样,它确实值得提出自己的问题。

// Why does the JavaScript treat
x?.y
// as
x === null || x === void 0 ? void 0 : x.y
// instead of
x === null || x === void 0 ? x : x.y
// ?
Run Code Online (Sandbox Code Playgroud)

x == null,后者会保存null,而前者总是返回undefined

现代浏览器?.本身就支持,因此我们可以测试此行为。

const test = () => {
  console.log('undefined?.x\t\t==>\t', undefined?.x);
  console.log('null?.x\t\t\t==>\t', null?.x);
  console.log('null?.x === null\t==>\t', null?.x === null);
};

try {
  eval('null?.x');
  test();
} catch {
  console.error('Your browser does not support optional chaining syntax.');
  console.info('While optional chaining is supported by all modern browsers, this will not work in browsers that do not support the syntax.')
  console.warn('');
  console.info('Shocking, I know.');
  console.info('Compatibility chart: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#browser_compatibility');
}
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 8

In the FAQ for the optional chaining proposal, it says:

\n
\n

Why does (null)?.b evaluate to undefined rather than null?

\n

\xc2\xa0\xc2\xa0a.b也不a?.b打算保留有关基础对象的任意信息a,而只是提供有关"b"该对象的属性的信息。"b"如果中不存在属性,则由和a反映。\n特别是,该值被视为没有属性;因此,是未定义的。a.b === undefineda?.b === undefinednull(null)?.b

\n
\n

所以这似乎是这个问题的预期面向公众的答案。该属性不存在,因此可选链接为您提供了读取不存在的属性 ( undefined) 的正常行为,而无需担心抛出TypeError.

\n
\n

当然,您并不是唯一一个期望a?.b传播无效性的人a(null)?.b关于(现已关闭)问题tc39/proposal-Optional-chaining#65tc39/proposal-Optional-chaining#69中应该包含什么内容,存在相当激烈的争论

\n

在 tc39/poc#65 中,我们看到进行了一项reddit 民意调查,一致认为“总是undefined”而不是“有时null”。在 tc39/poc#69 中,有人对 JS 库进行了调查,这些库具有此类运算符的函数版本,例如UndercorepropertyLodashget,并问道:“如果someLibraryFunction({a: 123}, "a")生成123,并且someLibraryFunction(undefined, "a")生成undefined,那么会生成什么someLibraryFunction(null, "a")?” 看起来undefined大多数咨询过的图书馆都得到了答案。

\n

undefined这些都不一定是我们使用而不是的明确原因null。但他们表明, 的力量undefined似乎比 的力量拥有更多的力量或耐力null,并且undefined最终占了上风,总是回到“a?.b应该让你阅读b的属性而a不用担心TypeError”的论点。

\n