0

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?

1
  • You probably should not use non binary values in binary operators. It may lead to unintuitive behaviour like that, especially knowing that 0 or "" (empty string) are falsy values. Commented Mar 25, 2021 at 16:07

4 Answers 4

2

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

Sign up to request clarification or add additional context in comments.

2 Comments

Similar customers also purchased: The ?? Nullish Coalescing Operator (treats null and undefined as "even falsier" than other falsy values) -- Add to Cart
Thanks! Especially the links to the MDN Web Docs are enlightening!
0

|| is in fact coalescing operator, not logical OR. It returns first non-falsey value of its operands, or last value otherwise

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.