frenchie
frenchie

Reputation: 52047

javascript if condition with multiple ifs

I'm running a UI component on every page and on one of the pages, there's an extra functionality linked to it. The UI component has a boolean called MyValue and the extra functionality has an object called ExtraObject and one of its properties is a boolean called ExtraBool.

I want to test if MyValue is true AND if ExtraObject.ExtraBool is false, BUT ONLY if ExtraObject exists. That way, if I'm on the pages that don't have ExtraObject, there's no error.

I tried this:

if (MyValue === true && 
    (typeof ExtraObject === undefined || ExtraObject.ExtraBool === false)) {...}

How should I rewrite this?

At the moment, I keep getting "ExtraObject is not defined error".

Thanks.

Upvotes: 2

Views: 189

Answers (4)

zzzzBov
zzzzBov

Reputation: 179256

Truth table time!

A is MyValue*
B is window.ExtraObject**
C is ExtraObject.ExtraBool

A B C | O
------+--
0 0 0 | 0
0 0 1 | 0
0 1 0 | n/a***
0 1 1 | 0
1 0 0 | 1
1 0 1 | n/a***
1 1 0 | 1
1 1 1 | 0

What we find with these values is that the simplest equation to produce O is:

A && !C

So your code should be:

if (MyValue && !ExtraObject.ExtraBool) {}

But of course, you mentioned not wanting to run into issues if ExtraObject wasn't defined:

var extraBool = window.ExtraObject ? ExtraObject.ExtraBool : false;
if (MyValue && !extraBool) {}

An alternative means of writing extraBool is:

var extraBool = window.ExtraObject && ExtraObject.ExtraBool;

You can then inline this:

if (MyValue && !(window.ExtraObject && ExtraObject.ExtraBool)) {}

An alternative of writing !(a && b) is !a || !b, which means that:

if (MyValue && (!window.ExtraObject || !ExtraObject.ExtraBool)) {}

is also correct.

* it could be MyValue===true depending on how strict you need to be
** alternatively typeof ExtraObject !== 'undefined'
*** it's not actually possible to have ExtraObject be undefined and access ExtraObject.ExtraBool

Upvotes: 1

Mattias Buelens
Mattias Buelens

Reputation: 20179

That should be:

typeof ExtraObject === "undefined"

typeof returns the type of the expression as a string, so you need to compare the name "undefined" to the result.

In my opinion, your condition is a bit too explicit. I'd go with something shorter:

if (MyValue && !(ExtraObject && ExtraObject.ExtraBool)) {...}

If you're communicating with your own GUI code, you can assume that the types are as expected. Type checking in JavaScript is rather cumbersome, so if you know what you're dealing with you can be less explicit. (This doesn't apply to user input though. Never trust user input.)

Upvotes: 2

user1019144
user1019144

Reputation: 1253

if ((MyValue === true) && (typeof ExtraObject === undefined || ExtraObject.ExtraBool === false)) {}

Upvotes: -1

Pointy
Pointy

Reputation: 413996

The logic is not quite correct:

if (MyValue && ExtraObject && !ExtraObject.ExtraBool) { ... }

I'm guessing that null would be a value ExtraObject shouldn't have either; that is, I presume that you r condition is really better stated that it should be a reference to an object.

Thus, the condition as I wrote it will be true when MyValue is "truthy", ExtraObject is a reference to a real object, and the property ExtraBool on that object is "falsy".

Sometimes it's necessary to make explicit comparisons to boolean constants, but in my opinion it's a code smell. (Of course, it can also be dangerous to just check truthiness/falsiness ...)

edit If your requirement is that the expression be true when MyValue is true and either ExtraObject is not a reference to an object or it's ExtraBool property is true, then I'd write that:

if (MyValue && (!ExtraObject || !ExtraObject.ExtraBool)) { ... }

Which is "better" is a matter of personal preference and experience.

Upvotes: 1

Related Questions