How does stacking the optional chaining (question-mark-dot) operator in Javascript behave?

huangapple go评论76阅读模式
英文:

How does stacking the optional chaining (question-mark-dot) operator in Javascript behave?

问题

I ran these experiments in the Chrome console:

a = {}
   -> {}
a.n.n.n.n.n.n.n
   -> Uncaught TypeError: Cannot read properties of undefined (reading 'n')
a?.n.n.n.n.n.n.n
   -> Uncaught TypeError: Cannot read properties of undefined (reading 'n')
a?.n?.n.n.n.n.n.n
   -> undefined

基于我对该操作符的理解,我本来期望会出现错误,除非所有的“点”都有一个前置的问号:子表达式 a?.n?.n 应该得到 undefined,而后续的 .n 应该导致错误。然而,在执行两次 ?.n 后,似乎发生了一些变化,读取 undefined 的属性 n 似乎是可以的,这显然是荒谬的。所以可能发生了其他事情。

有人可能会认为 ?. 在 undefined 上评估时会快捷整个剩余表达式,但这也不可能是情况,否则一个单独的 ?. 应该足以实现这一点。

?. 到底如何行为,以及这种行为如何解释我得到的结果?

英文:

I ran these experiments in the Chrome console:

a = {}
   -> {}
a.n.n.n.n.n.n.n
   -> Uncaught TypeError: Cannot read properties of undefined (reading 'n')
a?.n.n.n.n.n.n.n
   -> Uncaught TypeError: Cannot read properties of undefined (reading 'n')
a?.n?.n.n.n.n.n.n
   -> undefined

Based on my understanding of that operator, I would have expected an error unless all "dots" have a preceding question mark: The subexpression a?.n?.n should result in undefined, and the subsequent .n should crash. However, after doing ?.n two times, something seems to change and reading the property n of undefined seems to be okay, which is obviously nonsense. So something else is probably going on.

One might think that ?. shortcuts the whole remaining expression when evaluated on undefined, but this cannot be the case either, otherwise a single ?. should be sufficient to achieve that.

How exactly does ?. behave, and how does that behaviour explain the results I'm getting?

答案1

得分: 3

引用自问题:

> 有人可能会认为 ?. 在未定义的情况下缩短整个剩余表达式的计算

是的,这正是发生的情况。来自MDN的解释:

> 可选链 (?.) 运算符访问对象的属性或调用函数。如果使用此运算符访问的对象或调用的函数为 undefined 或 null,则表达式短路,评估为 undefined 而不是抛出错误。

当你访问 a.b.ca?.b.c 时:

  • a 评估为空对象
  • a.b 评估为 undefined
  • a.b.c 抛出错误,因为你正在从 undefined 访问 c 属性。

请注意,在 a 不是空值的情况下,在 a 后添加 ?. 是不必要的。

但是,在 a?.b?.c.da.b?.c.d 的情况下:

  • a 评估为对象,a?.b 像之前一样评估为 undefined。
  • 在评估 a?.b?.c 时:由于 a.b 是 undefined,它不会访问 c 属性并在此处短路,为整个表达式返回 undefined 值
英文:

Quoting from the question:

> One might think that ?. shortcuts the whole remaining expression when evaluated on undefined

Yes, that is exactly what is happening. From MDN:

>The optional chaining (?.) operator accesses an object's property or calls a function. If the object accessed or function called using this operator is undefined or null, the expression short circuits and evaluates to undefined instead of throwing an error.

When you access a.b.c or a?.b.c

  • a evaluates to the empty object
  • a.b evaluates to undefined
  • a.b.c throws an error because you are accessing c property from undefined.

Note that adding ?. after a is unnecessary here because a is not nullish.

But, in case of a?.b?.c.d or a.b?.c.d

  • a evaluates to an object and a?.b evaluates to undefined like before.
  • When evaluating a?.b?.c: since a.b is undefined, it doesn't access the c property and short circuits here and returns undefined value for the entire expression

答案2

得分: 1

这在文档的“短路”章节中有解释,此处

当在表达式中使用可选链时,如果左操作数为null或undefined,则不会评估该表达式。

特别是在第一个段落之后的句子:

随后的属性访问也不会被评估。

因此,这是已记录的行为,它很好地解释了您看到的行为,因为在您的示例中,

a?.n.n.n.n.n.n.n -> Uncaught TypeError: Cannot read properties of undefined (reading 'n')

a 不是 undefined,因此第一个 ?. 被评估为 a,然后运行时看到的下一个表达式是 a.n.n

英文:

This is explained in the "Short Circuiting" chapter of the documentation, here

> When using optional chaining with expressions, if the left operand is null or undefined, the expression will not be evaluated

Especially the sentence following that first paragraph:

> Subsequent property accesses will not be evaluated either.

So this is documented behavior, and it does well explain the behavior you see, because in your example

a?.n.n.n.n.n.n.n -> Uncaught TypeError: Cannot read properties of undefined (reading 'n')

a is not undefined, and thus the first ?. is evaluated to a and then the next expression the runtime sees, is a.n.n.

huangapple
  • 本文由 发表于 2023年5月15日 15:06:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76251619.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定