2

Currently I am (in many places in a project) checking to see if data exists at one object's root level, just to see if the next level exists, just to see the next and so on.

This might look something like this:

let name = display.data ? display.data ? data.name.bio ? data.name.bio.details ? :"Name N/A" : "Name N/A" : "Name N/A" : "Name N/A"

Instead of checking it this way, is there a way to make a call directly to data.name.bio.details that doesn't throw an error but silently falls back to being undefined?

E.g. if I call data.name.bio.details and data.name.bio doesn't exist, I'll get an error saying that and it's not so silent.

Could I do something like this, that wouldn't scream bloody murder when .bio doesn't exist?:

var name = data.name.bio.details || "Name N/A"

Hope this makes sense, not sure if there's a better approach!

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
Thingamajig
  • 4,107
  • 7
  • 33
  • 61
  • If the Object exists and it's an object property, you can do like `if(obj.prop === undefined){ /* not defined */}`. You can also simply test for `=== undefined` if the var is an argument or is declared with `var`, `let`, or `const`. If there is no declaration whatsoever you should do like `if(typeof yourVar === 'undefined'){ /* not defined */ }`. That last way works under all circumstances. Note, of course, that if your object is not defined then `if(typeof obj.prop === 'undefined'){}` would throw undefined error on the obj. – StackSlave Jul 09 '19 at 23:28

4 Answers4

4

Use logical AND && and OR ||:

var name = data && data.name && data.name.bio && data.name.bio.details || "Name N/A";

You could also use try/catch if you're not sure if data is defined- the above will throw a ReferenceError if data isn't defined:

try {
  var name = data.name.bios.details;
} catch(e) {
  var name = "Name N/A";
}
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
  • Yeah I guess this gets right of a bunch of the fallback/false cases – Thingamajig Jul 09 '19 at 23:16
  • 1
    Heads up, this requires data to be at least defined. – Matthew Jul 09 '19 at 23:17
  • Fixed @Matthew. – Jack Bashford Jul 09 '19 at 23:19
  • 2
    It works, but the try-catch is an intensive process. Honestly, I would be curious to benchmark using the try-catch against the in-line check and see the differences. – Matthew Jul 09 '19 at 23:22
  • "Intensive" is only relative. Won't matter for a low number of failure cases. Most micro-benchmarks (ie. 1,000,000 attempts) will swamp with worst-case scenarios that have no practical bearing in many real life scenarios: eg. if such an exception guard is used a few times (or even on a few hundred times..) per app, it really doesn't matter. – user2864740 Jul 09 '19 at 23:26
  • 2
    It shouldn't, but I also don't agree to use a try-catch for a simple null check in this case. It just seems lazy to me (Personal opinion). – Matthew Jul 09 '19 at 23:28
  • That's a different argument. – user2864740 Jul 09 '19 at 23:28
  • 1
    The `AND` / `OR` approach isn't really any better than the original solution in the question – James Jul 09 '19 at 23:48
1

If you're transpiling your code, check out tc39/proposal-optional-chaining.

There's a Babel Plugin that will handle it for you.

var name = data?.name?.bio?.details || "Name N/A"

Obviously this won't work as-is, yet, but worth considering if you are already using Babel (or similar)!

Dave Salomon
  • 3,287
  • 1
  • 17
  • 29
0

Honestly, mine would be similar to the other, but I would prefer this route.

EDIT:

I was thinking of another way to not have it so long-winded, I arrived this.

((typeof data != 'undefined') ? data.name && data.name.bio && data.name.bio.details && data.name.bio.details || "Name NA" : "Name NA")

It'll perform a null check against data and then it'll just eval using the other method (I honestly forget what it is called) and then it'll return the appropriate value.

EDIT: Fixed issue where it would fail in Edge. Tested in Edge, Chrome, and Firefox. Also removed the first method.

Matthew
  • 3,136
  • 3
  • 18
  • 34
  • 1
    Could start with `x && x.y && x.y.z..`: the ternary location looks of little value: maybe if it was *around* the conditions? Such will "potentially fail" for the edge-case of `x && x.str && x.str.length` .. just to keep truthiness rules around. – user2864740 Jul 09 '19 at 23:29
  • You are right. I have never realized that before. How would one check on Edge to see if a variable is null or undefined? I have done all the standard checks and each of them came back with a fail. Please tell me it isn't a try-catch. EDIT: Found it. – Matthew Jul 09 '19 at 23:34
0

!!yourVar above will check yourVar is not empty, not undefined, not null etc...

Vampire
  • 109
  • 1
  • 4