is && in short circuit logic the same as in if clauses? - javascript

Does the logical and operator (&&) or the logical or operator (||) have the same function in an 'if clause' as in it does in short circuit logic?
For example, && in short circuit should return the first falsey value, otherwise the last value if none is found: eg 0 && 1 returns 1. But if thats the case, how can it work in an if clause?
if (false && 1)
wont run because both conditions aren't true, yet short circuit seems to dictate that it will return 1, in which case 1 is a truthy value and the if clause should pass?
Edit: My mistake, I mixed up && and || in short circuit. They work the same as conditionals

&& in short circuit should return the first falsey value, otherwise the last value if none is found
Correct.
eg 0 && 1 returns 1
Nope. 0 && 1 returns the first falsey value, which is 0.
if (false && 1) wont run because both conditions aren't true
Correct. false && 1 returns the first falsey value, which is false. Since false is falsey, the if-statement doesn't run.
yet short circuit seems to dictate that it will return 1, in which case 1 is a truthy value and the if clause should pass?
Nope. As you said, it returns the first falsey value, which is false. The value of any of the later terms doesn't matter: if(false && something_that_crashes_the_browser()) works just as well.

Short circuit logic works the same as if-statement logic — there's really no difference, they're just conditionals:
console.log(0 && 1);
if (0 && 1) console.log("0 && 1");
console.log(false && 1);
if (false && 1) console.log("false && 1");

Related

Javascript OR Expression: return Operand that is *not* NaN

I have an OR expression that should return the operand that is anything else than NaN:
(1 || NaN) // evaluates to 1
(NaN || 1) // evaluates to 1
But when the other operand is also a falsy value like 0, null, undefined or false, Javascript returns always the rightmost operand:
(0 || NaN) // evaluates to NaN
(NaN || 0) // evaluates to 0
// same for combinations of 0, null, undefined and false
Is there a way to fit the desired behaviour "Return the operand that is not NaN" into a nice & short expression or do I have to rely on an if/else construct?
You could add a default falsy value at the end of the expression, like
result = yourValue0 || yourValue1 || 0;
In this case, you get either a truthy value of yourValueX or the last falsy value.
Use an if-else-expression, also known as the conditional operator:
!isNaN(a) ? a : b
Try this:
var notNaN = [value1, value2, value3].find(item => !Number.isNaN(item))
This kind of operators use a lazy mechanism for their computation and this concept is called short circuting in javascript. Basically, JS returns value as soon as it feels no more computation is required to evaluate this expression. So, if its an && operator it will return as soon as it finds first non-truthy(0, "", null, undefined, NaN) as for && operator if any of the operands is non-truthy there is no point check rest of the operands as expression is already non-truthy, so it returns that value and exits, now if all the operands are truthy it checks till last and returns the last value. For || its just the opposite as soon as it finds first truthy value it returns otherwise keeps checking till last and returns it.

JavaScript Syntax: actual = node.nodeType === 1 && node.getAttribute(att) [duplicate]

I don't understand how &&, ||, and ! work... both with bools and other data types. How do you use them?
All values in JavaScript are either “truthy” or “falsy”.
a && b evaluates to the first falsy operand,
a || b evaluates to the first truthy operand.
Both operators will not evaluate any operands after the one the return.
If all operands don’t match, they will evaluate to the last one.
!a evaluates to true if a is falsy and false if a is truthy.
All values are truthy except the following, which are falsy:
null
undefined
false
+0
-0
NaN
0n
""
document.all
If you want to test that both of two conditions are truthy then use &&:
if (isX && isY)
{
// Do something.
}
If you want to test that one or both of two conditions are truthy then use ||:
if (isX || isY)
{
// Do something.
}
The ! inverts a boolean (a truthy value becomes false and vice versa).

Why does this set of logical operators work correctly?

So I'm doing a puzzle to evaluate Kaprekar's Routine and in the first section I need to check to make sure the 4 digit input has at least two unique digits so I did this:
let numArr = num.toString().split("");
if (numArr[0] == numArr[1] && numArr[2] && numArr[3]) {
return 0;
}
I tried searching but I keep finding links to short-circuiting operators. I was expecting to write out numArr[0] == into every && block but to my surprise it worked. Can anyone explain why this returns 0 for 3333 but does not for 1234? I assumed numArr[2] and numArr[3] would just evaluate to true automatically.
There is a thing called operator precedence. The operator with higher precedence happens first. == happens before &&. When you have more than one operator of the same precedence it goes by 'associativity' which is generally left to right (= for example is right to left); so let's take another look at your code
if ( ((numArr[0] == numArr[1]) && numArr[2]) && numArr[3] )
Let's take just the first piece. Doing 3 == 3 is true and since none of the operators are 0, the if statement is true. But with 1234, 1 == 2 is false, so the expression short circuits to false. Generally when something (like an if statement) accepts a boolean value && a non zero/undefined/false value, the expression is considered true (I may be wrong). If you do the below you should get true
if ( numArr[0] && numArr[1] && numArr[2] && numArr[3] )
To answer your other question, generally when people work with a set of data in JS they use lodash. You can find the if there is 2 unique values easily with the line blow. uniq(array, func) returns an array with unique values in the same order. See the documentation
_.uniq("3333".toString().split(""), v=>v).length >= 2 //false
_.uniq("1224".toString().split(""), v=>v).length >= 2 //true
It is because
For String 3333
num[0] is 3,num[1]=3,num[2]=3,num[3]=3
Expressions evaluate based on precedence of operators
and when the operators have the same precedence they get executed from left to right
In this case == has highest precedence over &&
so,
num[0]==num[1] ,it is 3==3 true
then
true && num[2] && num[3] => true&&3&&3 => true
For string 1234
num[0]=1,num[1]=2,num[2]=3,num[3]=4
num[0]==num[1] ,1==2 is false
so now the expression is
false && num[2] && num[3]
For && operator if the first operand is false,it ignore the rest of the expression
so now it just results as false
Hope this helps
You have three expressions being evaluated
// loose-equality, so true if after type-coersion, the values are equivalent
// this is the only condition that is actually changing in your code, unless
// you have a number with less than 4 digits
numArr[0] == numArr[1]
// is a non-empty string so it's 'truthy'
numArr[2]
// is a non-empty string so it's 'truthy'
numArr[3]
Anything that is not Falsy (false, 0, "", null, undefined, and NaN) is Truthy
Therefore, you need to write additional code to check for unique digits.

JS && precedence vs ===

According to javascript documentation, the === operator is higher precedence than && operator. Therefore, I would expect an expression like
false && undefined.foo() === undefined.foo()
to throw an error while evaluating either one of undefined.foo() calls. However, as I've tried in node, chrome, and firefox, the js engine always short circuits and returns false e.g.
> false && undefined.foo() === undefined.foo()
false
Shouldn't && short circuit kick in after === operands have been evaluated?
The higher precedence merely means that both operands undefined.foo() are associated with the === operator first before the operands for && are decided. It does not dictate the order of execution, which is still left to right.
Operator precedence merely decides whether the expression is evaluated as
(false && undefined.foo()) === undefined.foo()
or
false && (undefined.foo() === undefined.foo())
In either case false is still the first thing that's being evaluated; though if && had the higher precedence (first parenthesised example) then the 2nd undefined expression would always be evaluated too.
To better visualize why the precedence is being parsed the way it is, add in optional parenthesis according to how the interpreter ranks precedence:
( (false) && ( undefined.foo() === undefined.foo() ) )
Because === has higher precedence than &&, parenthesis gets added around the undefined.foo() === undefined.foo() expression first. Since precedence has now been determined, JavaScript interpreters will now parse it from left to right. Due to short-circuit evaluation, the undefined.foo() comparison expression never gets evaluated since the condition exits upon evaluating the false

Retrieve the result of an OR logic operation in JS

A logical statement always returns a boolean value, true or false.
But how do you retrieve the true statement in a OR logical operation?
In JavaScript, the OR and AND operators always return one of their operands. The OR operator returns the first falsy operand (and doesn't evaluate any operands after that) or the last operand if they are all truthy. The AND operator similarly returns the first truthy operand or the last operand if they are all falsy.
If you wish the result to be a boolean, you can use the ! operator which returns true for falsy values and false for truthy values.
To sum it up:
!!(a || b) will return true if a and/or b are truthy and false otherwise.
a || b will return a if a is truthy and b otherwise.
EDIT:
After some explanations it seems that what you are looking for is separating the evaluation of the OR.
if (a === 56) {
// a is what you are looking for
} else if (b === 56) {
// b is what you are looking for
} else {
// neither a nor b are what you are looking for
}
The above piece of code does the exact same evaluations as your code but you have a branch of code that executes when the first expression is true and another branch which executes if the first expression is false and the second expression is true.

Categories