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

Why does JavaScript's optional chaining use undefined instead of preserving null?

这是我在评论中指出的 As resident TypeScript legend 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
// ?

x == null时,后者会保留null而前者总是returns 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');
}

FAQ for the optional chaining proposal 中,它说:

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

  Neither a.b nor a?.b is intended to preserve arbitrary information on the base object a, but only to give information about the property "b" of that object. If a property "b" is absent from a, this is reflected by a.b === undefined and a?.b === undefined. In particular, the value null is considered to have no properties; therefore, (null)?.b is undefined.

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


当然,您并不是唯一期望 a?.b 应该 传播 a 的无效性 的人。关于 (null)?.b 应该在(现已关闭的)问题 tc39/proposal-optional-chaining#65 and tc39/proposal-optional-chaining#69.

中的内容存在相当热烈的争论

在tc39/poc#65中我们看到一个reddit poll was conducted and the consensus favored "always undefined" over "sometimes null". And in tc39/poc#69 someone did a survey of JS libraries that had function versions of this sort of operator like Undercore's property and Lodash's get,然后问:“如果someLibraryFunction({a: 123}, "a")产生123,而someLibraryFunction(undefined, "a")产生undefinedsomeLibraryFunction(null, "a") 产生什么?”对于所咨询的大多数图书馆,答案似乎是 undefined

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