loading...
Cover image for Nulling JavaScript

Nulling JavaScript

kayis profile image K ・2 min read

Don't you love huge object graphs in JavaScript? Like, when you get some nice data from that JSON API and have to look so deep into it, you just hope it doesn't look back?

Well, more often than not it does and then things get messy and you curse that damn JavaScript for not providing you with better tools and you forget that you just have modeled out that data structure with nice access interfaces in the first place.

Like most of you lazy bums I just love my plain old JavaScript objects and if I wanted the language to help me I would have used a statically typed one anyway, right? ;)

Long time, the solutions (besides really modeling your data) were looong checks or third party libs.

    let myValue = "default";
    if (response && response.body && response.body.somethingElse) {
      myValue = response.body.somethingElse.myValue;
    }

    import _ from "lodash";

    const myValue = _.get(response, "body.somethingElse.myValue", "default");
Enter fullscreen mode Exit fullscreen mode

But, fear no more my fellow JavaScripters, for we will soon conceive the infamous Null Propagation Operator!

What does it do?!

It lets you access the depth of your data without the fear of everything blowing up when that darn back-end dev just changed the structure again.

    const myValue = response?.body?.somethingElse?.myValue || "default";
Enter fullscreen mode Exit fullscreen mode

It will even work with arrays or functions


    const someValueFarAway = myArray?.[993];

    const calculatedIfAvailable = myFunc?.(10);

Enter fullscreen mode Exit fullscreen mode

But when will we have it?!

I have no idea...

At the moment this proposal seems to be Stage-2 and a Babel plugin is in the works.

The question is now, is it a blessing or a curse from the JavaScript gods?

Will it make code more robust with less thinking or will all the silent errors accumulate to silent time bombs under our asses?

Like so often, I just don't know...

Discussion

pic
Editor guide
Collapse
rpalo profile image
Ryan Palo

Is there a reason not to use a Try/Catch block? That seems a little more explicit, but I'm not sure, maybe that's not idiomatic for JavaScript. I haven't done enough big JavaScript to know. At least in Python, it seems like it would work well enough to:

try:
    myValue = response.body.something_else.my_value
except AttributeError:
    myValue = "default"

I guess using a block is maybe not at shwoopy as one quick line, like above.

Collapse
kayis profile image
K Author

You're totally right. Somehow JS devs aren't too fond of try-catch, guess it's like you said: too explicit?

Maybe it has also to do with the async nature of JS code, you simply couldn't catch them callbacks, so many people didn't use it too often.

Collapse
joelnet profile image
JavaScript Joel

I have been told "Avoid using exceptions for control flow". If you know something might throw an exception and you can check for it, do that instead.

A try block is also greedy and you may end up swallowing more than what you were hoping for, which can be a PITA for chasing down odd errors.

Thread Thread
kayis profile image
K Author

Yeh, in statically typed languages you can at least easily filter what you wanna catch :/

Collapse
rpalo profile image
Ryan Palo

Ooh that makes sense. Cool, thanks!

Collapse
nomaed profile image
Nomæd

Try-Catch aren't popular in JS because engines can't optimize the code well, or something of this sort that I read somewhere a while ago. I use Try-Catch with promises quite often.

Thread Thread
kayis profile image
K Author

I read that's the case for many languages.

Collapse
_prelevic profile image
Mark

isn't that why you now have promises and the .catch() there?

Thread Thread
kayis profile image
K Author

sure, but you're not always inside a promise

Collapse
22samuelk profile image
Samuel

What about...

const value = (() => {
 try {
   return object.x.y
 } catch (err) {
   return 'default'
 }
})()

Easy as that... cough

Collapse
22samuelk profile image
Samuel

I mean, we could also do this (to get rid of the IIFE), but that's unfunctional, and I don't wanna use a let tbh.

let value
try {
  value = object.x.y
} catch (err) {
  value = 'default'
}

Another option would probably be this, but ew, async where we don't need it...

const value = await new Promise(resolve => resolve(object.x.y))
  .catch(err => 'default')

So yeah, maybe we do need this new operator, although I really am worried about handling probably-invalid data structures. I mean, isn't that an indicator we should probably write our code a different way? Maybe we should, for example, use another function to handle that specific input, which should be checked before that? I don't know, just speculating.

Thread Thread
kayis profile image
K Author

yes, like I said model your data right and things get more robust.

The promis catching is nice and I prefer it, but sometimes await is nicer in a specific case and you have to try-catch, I guess ?. would be simpler then.

Collapse
elmuerte profile image
Michiel Hendriks

Exceptions are generally really expensive. Actual usage of them should be an exceptional case.

Collapse
maestromac profile image
Mac Siri

Oh sweet this is just like Safe Navigation. I definitely see this as a blessing but I hope folks won't be chaining it more than 3 times. Just thinking about all the possible silent errors gives me the heebie-jeebies 😨

Collapse
kayis profile image
K Author

Maybe it's not a huge problem if people don't just let it short circuit to null and use sane defaults all the time.

Collapse
rhymes profile image
rhymes

I like the idea. Kind of like Ruby's operator &. which works the same way:

response&.body&.somethingElse&.myValue || "default"
Collapse
andreujuanc profile image
Juan C. Andreu

Sometimes I feel like JS will be the dynamic version of C#.
SharpScript? xD (I know there is TS, but TS has to be transpiled)

Each iteration has less and less similarities to java.

Collapse
kayis profile image
K Author

How much did the first have?

I mean, there are some with Java, but also with Lua and C.

Collapse
andreujuanc profile image
Juan C. Andreu

Not much I guess. D:

Collapse
andy profile image
Andy Zhao (he/him)

I think it could be really useful! I'm no JS expert, but I hate having a bajillion booleans just to make some value default. I could live with the syntax, too, so that's a plus.

Collapse
kayis profile image
K Author

I just blame the back-end ;)

Collapse
ciantic profile image
Jari Pennanen

It remains in Stage 1, see this long post in TypeScript issue, they've discussed it, but not very thoroughly as pointed there.

Collapse
kayis profile image
Collapse
damcosset profile image
Damien Cosset

Whenever I see articles like that, I'm always excited for the future of the language. Lots of great things coming ( some day... )

Collapse
kayis profile image
K Author

I'm not always so sure. Often I think WTH? and then I have to try it.

For example, sometimes I like await and sometimes a promise, .then().catch() is often nicer to write than a whole try-catch with await. etc.

Also I looked into observables and found them incredible powerful, but then I used async-await in some apps a few times and it was often a nice simplification and an observable would have been overkill.