2

I was very surprised to see the following behavior in Node 14.18.0:

> {}?.fun();
Uncaught TypeError: b?.fun is not a function
> undefined?.fun();
undefined

I understand why the first statement throws a TypeError. {}?.fun is undefined, which is not callable. But undefined?.fun is also undefined, so why can it be called without throwing? What part of the ECMAScript specification defines this behavior? Did the ECMAScript working group provide any reasons why it should work this way?

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
A. R.
  • 2,031
  • 13
  • 27
  • 9
    Because the optional chaining for `undefined` stops at `undefined`. Since `{}` is an actual object—without a method called `fun()`—it blows up, because you called a function that did not exist. – Mr. Polywhirl Sep 28 '21 at 13:51
  • 1
    The whole point of `?.` is to stop traversing the object graph when the left-hand side is `undefined`. – Pointy Sep 28 '21 at 13:53
  • I’m not sure how it *couldn’t* work this way—it’s not calling `fun` because evaluation stopped at `undefined`. – Dave Newton Sep 28 '21 at 13:53
  • I had just assumed that `?.` was left-associative just like `.` (i.e. `a?.b?.c <-> (a?.b)?.c`). I hadn't guessed it was short-circuiting. – A. R. Sep 28 '21 at 13:54
  • If anybody wants to write an answer, I will be happy to accept. – A. R. Sep 28 '21 at 13:55
  • 3
    [Short-circuiting evaluation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#short-circuiting_evaluation): _"When using optional chaining with expressions, if the left operand is `null` or `undefined`, the expression will not be evaluated."_ -> [How much research effort is expected of Stack Overflow users?](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users) – Andreas Sep 28 '21 at 13:55
  • It is left-associative. It's in section 12.3.9.2 of the 2020 spec. If the expression to the left of `?.` evaluates to `undefined` or `null`, the whole chain evaluates to `undefined`. – Pointy Sep 28 '21 at 13:57

2 Answers2

4

During optional chaining, if the current value within the chain is null or undefined, the expression short-circuits with a return value of undefined.

This is in the official docs:

The ?. operator is like the . chaining operator, except that instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined. When used with function calls, it returns undefined if the given function does not exist.

Since {} is an actual object—without a method called fun()—it blows up, because you called a function that did not exist.

To fix your issue, you will need to call the function with optional chaining:

console.log(({})?.fun?.()); // undefined
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
-5

the work of? and say that possibly the value is undefined

normally used like this in typescript

console.log(myobj?.value ?? 'does not exist');

in javascript "?" it's useless

"?" doesn't do anything, it just signals that the value can be undefined, so when you put an object, it returns an error because this property doesn't exist in your object, whereas in undefined javascript it just ignores everything

john
  • 4
  • 3