skip to Main Content

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?

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search