Reputation: 52047
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
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
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
Reputation: 1253
if ((MyValue === true) && (typeof ExtraObject === undefined || ExtraObject.ExtraBool === false)) {}
Upvotes: -1
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