Javascript boolean logic (comparing double bang with truthy/falsy values) - javascript

I'm inspecting some code and I found something I'd like to run by Javascript veterans. I feel pretty comfortable with Javascript but I've always manage to run into something that makes me say, "I didn't know that about Javascript!"
I'm hoping this is one of those situations:
if (this.props.referralId != prevProps.referralId ||
this.props.referralValidationStatus != prevProps.referralValidationStatus ||
this.props.customerName != prevProps.customerName &&
!!prevProps.personId != !this.props.personId) {
// perform whatever logic is here...
}
My questions:
Does JS know how to automatically identify the mixture of || and &&? Or is this code missing parenthesis's around the || comparison?
Just as it's explained here, is it fair and should I expect the obvious behavior when comparing a boolean against a truthy/falsy value?
I'm baffled on what the logic should be here. If I were to rewrite this I would do like so:
if ((this.props.referralId !== prevProps.referralId ||
this.props.referralValidationStatus !== prevProps.referralValidationStatus ||
this.props.customerName !== prevProps.customerName)
&& (!!prevProps.personId === !!this.props.personId)) {
// Perform logic
}
However, I'd like to confirm and make sure I'm not missing something I might have missed about JS.
Thank you in advance for confirming my hunch or educating my on something new when it comes to JS. Looking forward to your comments and/or answers.

Like most languages, there's a precedence rule in Javascript. && are evaluated before || as you can see here. So, if you need to check all the ors and then use the final result to make the and, you are right! Use the parenthesis.
You are also right about the !! refactoring:
!!prevProps.personId != !this.props.personId
Is the same as:
!!prevProps.personId === !!this.props.personId
In other words it is checking if both prevProps.personId and this.props.personId has some value (evalatued to True as boolean), or if both are empty/undefined/Nan (evaluated to False as boolean).

The first statement says (pseudocode):
if (
//the first statement returns truthy
this.props.referralId != prevProps.referralId ||
// or the second statement returns truthy
this.props.referralValidationStatus != prevProps.referralValidationStatus ||
// or the combination of the third and fourth statements returns truthy
this.props.customerName != prevProps.customerName
&&
!!prevProps.personId != !this.props.personId
)
// then...
{
// perform whatever logic is here
}
Your rewritten version says (pseudocode):
if (
// one of these three statements is truthy
(this.props.referralId !== prevProps.referralId ||
this.props.referralValidationStatus !== prevProps.referralValidationStatus ||
this.props.customerName !== prevProps.customerName)
&& // AND!
// this statement also evaluates truthy
(!!prevProps.personId === !!this.props.personId)
)
// then...
{
// perform whatever logic is here
}
Hopefully this explains the differences between the code blocks.
#rafaelodon is otherwise correct

Related

What's the common way to check if a field is null or undefined (but not zero or empty string) in Javascript? [duplicate]

Although there are semantic differences between JavaScript's null and undefined, many times they can be treated as the same. What's the preferable way of checking if the value is either null or undefined?
Right now I'm doing the following:
if (typeof value === "undefined" || value === null) {
// do something
}
Which is pretty verbose. I could, of course, create a function for this and import everywhere, but I'm wishing that there's a better way to achieve this.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
No, it gets the job done 100% of the time. The only values that are == null are null and undefined. 0 == null is false. "" == undefined is false. false == null is false. Etc. You're confusing == null with falsiness, which is a very different thing.
That's not to say, though, that it's a good idea to write code expecting everyone to know that. You have a perfectly good, clear check in the code you're already using. Whether you choose to write value == null or the explicit one you're currently using (or if (value === undefined || value === null)) is a matter of style and in-house convention. But value == null does do what you've asked: Checks that value is null or undefined.
The details of == are here: Abstract Equality Comparison.
underscore js has a function for this _.isUndefined()
from https://underscorejs.org/#isUndefined
isUndefined _.isUndefined(value)
Returns true if value is undefined.
example:
_.isUndefined(window.missingVariable);
=> true
lodash has a similar function. see https://lodash.com/docs/4.17.11#isUndefined
Both have similar functions for isNull too.
I find the functions are useful for others to know what is being tested for.

ensure undefined in accessing object don't break the enitre app

One annoying thing about writing js app is that nested object can caused error and break down the entire app.
if(result.applicant._id === null || applicant_id !== result.applicant._id.toString()){
console.log('redirect user');
}
Given above code, it can be dangerous, what if result.applicant._id is null? then toString will be invalid because it can't be undefined.toString(). How to ensure toString() work in this case? I can do
if(result.applicant._id === null || applicant_id !== (result.applicant._id && result.applicant._id.toString())){}
but that's so unclean. I found that I'll have many duplication just for the sake of checking something exist using js.
Your version works without ever hitting undefined.toString() because the if condition will be short-circuited (short-circuitted?) as result.applicant._id === null would evaluate as true and never evaluate applicant_id !== result.applicant._id.toString().
The test is already there no need to add extra checks in this case.
Update Just realised the === will not match undefined.
Just change the first part to result.applicant._id == null which will match undefined and null.
if (result.applicant._id == null || applicant_id !== result.applicant._id.toString()){
console.log('redirect user');
}
I know you may end with linting warnings but in this case that's exactly what you want.
A bit of short-handing might give you the cleaner code you're looking for.
As long as 0 is not a valid application id:
const id = result.application._id || 0;
if(!id || applicant_id !== id.toString()){
// redirect
}
Edit: To explain - the || in the variable declaration assigns the value to the first truthy value - or the second. Therefore, if the value is undefined, it will fall to the second value (0) which is still falsey and will fail the check, but can still have .toString() called on it.
Edit 2: If your ids are just numbers (which is what it looks like) then you actually don't need to convert it to a string - just let JavaScript's coercion to the work for you by using != instead of !==
const id = result.application._id || 0;
if(!id || applicant_id != id){
// redirect
}
In JavaScript, 12 == '12' is true. 12 === '12' is false. Generally the advice is to use === unless you consciously want to take advantage of coercion, and this seems like a good case for it :)
🏄 The shortest way could be this:
.: UPDATED :.
const applicant = result.applicant || {}
if (applicant_id !== `${applicant._id}`) {
console.log('redirect user');
}

Javascript: var1 == true && (var2 = true)

I see in the code I am working on often the following code style;
var1 == true && (var2 = true)
After some testing I figured it comes down to:
if (var1 == true) {
var2 = true;
}
Is this correct, or is there more to it? And why would anyone use this since the readability just dramatically reduces, since your assume at first glance it is just a check on two variables. So you really have to start looking at single or double equal sings and where the parentheses are, which just kinda, you know.. Just curious here..
Yes, this is equivalent. As far as I know, it is called short-circuit evaluation, describing the fact that the interpreter will return false for the whole boolean expression as soon as one of its parts is falsy.
Indeed, in your example it DOES reduce readability. But I think of it as just another tool in your toolbox you may use when you feel it could be useful. Consider the following:
return user && user.name;
This is one example when I tend to use it. In this case, I think it's actually more readable than
if (user) {
return user.name;
} else {
return undefined; // or null or something alike
}
UPDATE
I want to give you another example when I consider this kinds of constructs useful. Think of ES6 arrow functions like user => user.name. It does not need {} to open a body since it just has one line. If you wish to log something to the console (for debugging), you would end up having
user => {
console.log(user); // or something alike
return user.name;
}
You might as well use the shorter variant
user => console.log(user) || user.name
since console.log returns undefined after logging into the console, hence user.name is returned.
Yes, as you've mentioned there's more to it.
the first part var1 == true checks whether ther result is true or false.
if the condition is false the code after it doesn't get checked or evaluated and thus var2 doesn't get set to true.
But if the first part of the condition var1 == true is true which obviously is true, the second part of the conditional statement the part after && is checked.
now the second part of the condition is an operation it sets (var2 = true) which is kind of a truthy operation.
we could edit your code a little bit to help you understand the operation more clearly:
if( var1 === true && (var2 = true)){console.log('good');}
I hope this helps

How can avoid !! comparation in JavaScript?

I am using this "!!" comparation in order to compare with "undefined". However, is there any other way to do it?
isWidgetTemplatesLoaded: function(widgetName) {
return !!templates[widgetName];
}
Thanks
You could use typeof to check for undefined:
(typeof templates[widgetName] !== 'undefined')
typeof always returns a string. It returns "undefined" if the value of the variable is undefined or the variable does not exist.
You can use the typeof operator
typeof templates[widgetName];
else you can also use like this
if (templates[widgetName] === undefined) {
// rest of code
}
else {
// rest of code
}
To check for undefined you can just use the no-conversion equal/different operators:
if (x !== undefined) { ... }
if (y === undefined) { ... }
note however that this doesn't have the exact same meaning of !!. The double-negation for example returns true even for false, null, 0 or "" despite the fact that these values are not undefined.
By the way in Javascript you should basically always use === and !== instead of == and !=, unless you really need the crazy implicit conversion that equality/different operators do (and no one needs that). Good Javascript editors will warn you about any use of == or != as they are just bug-hiding places.
In the specific of your question code the !! logic seems wrong on a philosophical level because an empty template could be "" and this function would say that the template has not been loaded while instead it has been loaded and simply happens to be the empty string.
You could use the in operator, if you know, if the property exist with some value, other than undefined.
return widgetName in templates;

Checking for null or undefined

Although there are semantic differences between JavaScript's null and undefined, many times they can be treated as the same. What's the preferable way of checking if the value is either null or undefined?
Right now I'm doing the following:
if (typeof value === "undefined" || value === null) {
// do something
}
Which is pretty verbose. I could, of course, create a function for this and import everywhere, but I'm wishing that there's a better way to achieve this.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
No, it gets the job done 100% of the time. The only values that are == null are null and undefined. 0 == null is false. "" == undefined is false. false == null is false. Etc. You're confusing == null with falsiness, which is a very different thing.
That's not to say, though, that it's a good idea to write code expecting everyone to know that. You have a perfectly good, clear check in the code you're already using. Whether you choose to write value == null or the explicit one you're currently using (or if (value === undefined || value === null)) is a matter of style and in-house convention. But value == null does do what you've asked: Checks that value is null or undefined.
The details of == are here: Abstract Equality Comparison.
underscore js has a function for this _.isUndefined()
from https://underscorejs.org/#isUndefined
isUndefined _.isUndefined(value)
Returns true if value is undefined.
example:
_.isUndefined(window.missingVariable);
=> true
lodash has a similar function. see https://lodash.com/docs/4.17.11#isUndefined
Both have similar functions for isNull too.
I find the functions are useful for others to know what is being tested for.

Categories