tc39 / proposal-optional-chaining

https://tc39.github.io/proposal-optional-chaining/
4.94k stars 75 forks source link

global root behavior #60

Closed jseter closed 5 years ago

jseter commented 6 years ago

Should there be any definition for what occurs if the root of the expression does not exist?

i.e. code expects a global namespace 'cordova', but in some situations it may not be defined. normally you could only check via an initial typeof cordova !== "undefined" unless you are able to get an instance of the global object to use as your root in the expression instead.

ljharb commented 6 years ago

I would assume it would work like any variable reference - it it ended up as nullish, then the chain would be short circuited.

Tyler-Murphy commented 6 years ago

I think it'd be nice for it to throw an error, similar to the following reference error:

$ node
> x.y
ReferenceError: x is not defined
    at repl:1:1
    at ContextifyScript.Script.runInThisContext (vm.js:44:33)
    at REPLServer.defaultEval (repl.js:239:29)
    at bound (domain.js:301:14)
    at REPLServer.runBound [as eval] (domain.js:314:12)
    at REPLServer.onLine (repl.js:433:10)
    at emitOne (events.js:120:20)
    at REPLServer.emit (events.js:210:7)
    at REPLServer.Interface._onLine (readline.js:278:10)
    at REPLServer.Interface._line (readline.js:625:8)
> x = undefined
undefined
> x.y
TypeError: Cannot read property 'y' of undefined
    at repl:1:2
    at ContextifyScript.Script.runInThisContext (vm.js:44:33)
    at REPLServer.defaultEval (repl.js:239:29)
    at bound (domain.js:301:14)
    at REPLServer.runBound [as eval] (domain.js:314:12)
    at REPLServer.onLine (repl.js:433:10)
    at emitOne (events.js:120:20)
    at REPLServer.emit (events.js:210:7)
    at REPLServer.Interface._onLine (readline.js:278:10)
    at REPLServer.Interface._line (readline.js:625:8)

At least for me, something like x.y is usually a typo if x hasn't been defined, and I'd like it to throw a ReferenceError.

Is that what you mean?

jridgewell commented 6 years ago

This should definitely be throwing a reference error for undeclared variables.

ljharb commented 6 years ago

if x.y already throws a ReferenceError, so would x??.y - the optional chain applies to the member access, not to the lookup of x itself.

pharos42 commented 6 years ago

You’re right. It should probably only deal with defined values/nullish and continue to throw in this case. For the most part this question is about being explicit in the proposal whether it handles them in any special way, but perhaps that could also be made clear by the grammar for acceptable inputs. Thanks

ljharb commented 6 years ago

I think it's explicit that it doesn't handle the a any differently in a??.b etc, because it only addresses the .b part.

alangpierce commented 6 years ago

See https://github.com/tc39/proposal-nullish-coalescing/issues/13 and https://github.com/tc39/proposal-optional-chaining/issues/17#issuecomment-360300330 for some previous discussion on this.

CoffeeScript chose to make someUndeclaredVariable?.foo return undefined rather than crashing, which is occasionally useful and used in practice (e.g. window?.foo when you don't know if you're running in a browser). The big downside is that it silently ignores misspelled variable names (or other mistakes) in the 99% case when you're using a variable that you meant to declare, so I think the right behavior in JS is to throw ReferenceError if the variable is undeclared.

littledan commented 6 years ago

Agree with the points in this thread. Optional chaining isn't a general error suppression mechanism but rather much more specific.