Reputation: 85
In JavaScript you can check whether a variable has any value like this
if (strValue) {
//do something
}
Today I encountered something beyond my understanding, a conditional where I used this wasn't working as I expected. I had some JavaScript code that looked similar to below snippet.
var blnX = false;
var intX = 3;
var strX = "2021-03-25T13:53:13.259352Z";
function test(blnValue, intValue, strValue) {
return !blnValue && (intValue == 2 || ((intValue == 3 || intValue == 4) && strValue));
}
var result = test(blnX, intX, strX);
At this point I expected result
to be true
but it contained "2021-03-25T13:53:13.259352Z"
.
When I change the return
statement like below,
return (((intValue == 3 || intValue == 4) && strValue) || intValue == 2) && !blnValue;
or like this,
return !blnValue && (intValue == 2 || (strValue && (intValue == 3 || intValue == 4)));
then it does return true
.
To make it even more confusing when I change the function from the above snippet like below, then it does work like expected.
function test(blnValue, intValue, strValue) {
if (!blnValue && (intValue == 2 || ((intValue == 3 || intValue == 4) && strValue)))
return true;
return false;
}
Can someone explain to me why the conditional from the return
statement used in the first function is not returning the expected boolean value?
Upvotes: 0
Views: 641
Reputation: 2669
Maybe it might help to consider, step by step, how return !blnValue && (intValue == 2 || ((intValue == 3 || intValue == 4) && strValue));
is evaluated:
/*
* GIVEN:
* blnValue = blnX = false;
* intValue = intX = 3;
* strValue = strX = "2021-03-25T13:53:13.259352Z";
*/
/*0*/ !blnValue && (intValue == 2 || ((intValue == 3 || intValue == 4) && strValue));
/*1*/ !false && (3 == 2 || (( 3 == 3 || 3 == 4) && '2021-03-25T13:53:13.259352Z'));
/*2*/ true && (false || ((true || false) && '2021-03-25T13:53:13.259352Z'));
/*3*/ true && (false || (true && '2021-03-25T13:53:13.259352Z'));
/*4*/ true && (false || '2021-03-25T13:53:13.259352Z');
/*5*/ true && '2021-03-25T13:53:13.259352Z';
/*6*/ '2021-03-25T13:53:13.259352Z';
Also notice that:
const a = true && '2021-03-25T13:53:13.259352Z';
const b = '2021-03-25T13:53:13.259352Z' && true;
console.log(a); // -> '2021-03-25T13:53:13.259352Z'
console.log(b); // -> true
Upvotes: 0
Reputation: 5581
Expressions don't always return true
or false
in Javascript. They return the value of the last thing that they evaluated.
An easy trick to convert anything to true
or false
is to use a double-exclamation. One exclamation will give the opposite of the truthfulness of the expression, so two will switch it back to its original boolean equivalent.
See the sample code.
const a = 'hello'
const b = 1
console.log(b && a)
// outputs 'hello' since 'a' was the last evaluated thing
console.log(b || a)
// outputs 1 since 'b' was truthy and no need to evaluate a
console.log(!!(b || a))
// outputs true since !! quickly converts to boolean
Upvotes: 0
Reputation: 5940
You just have to understand how ||
or &&
work.
2 && 3
will return 3
, because if the left operand is truthy, the right operand is returned. That's all.
It works in a if
because 3
is truthy, so
if(2 && 3) {
console.log("bip"); // will be displayed.
}
Truthy/falsy and boolean values are two different things.
Some reading:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR
https://developer.mozilla.org/en-US/docs/Glossary/Falsy
https://developer.mozilla.org/en-US/docs/Glossary/Truthy
Upvotes: 2
Reputation: 298
||
is in fact coalescing operator, not logical OR. It returns first non-falsey value of its operands, or last value otherwise
Upvotes: 0