Javascript simplified if-statement - javascript

I'm scratching my head trying to understand this very simplified if statement. When searching for the answer, all I find is answers related to ternary operators.
Anyway. Why is it that the first case below works, while the latter throws an ReferenceError? Just trying to understand how things work.
true && alert("test")
var x;
true && x = 10;

This has to do with operator precedence. As the && operation is computed before the =, your second example would end up making no sense : (true && x) = 10;
For your second case to work, add parenthesis this way :
var x;
true && (x = 10);

Javascript seems to give higher precedence to && than to the assignment operator. The second line you gave is parsed as:
(true && x) = 10;
If you add parenthesis around the assignment, I think you will see the behavior that you were expecting:
true && (x = 10); // Sets x to 10 and the whole expression evaluates to 10.
And just in case you needed a pointer as to why && can be used as an if-statement, the phrase "short-circuit evaluation" might help.

It'a Operator precedence.
As you can see && has higher priority than =
So true && x = 10; is actually (true && x) = 10; which is clearly wrong. You can only assign value to variables, and (true && x) is either false or the value of x.

The result of alert() is undefined. So first example could be retyped as:
var x; // x is now 'undefined'
true && x; // true and undefined is undefined
The second example is about operators priorities. Runtime evaluate expression as (true && x) = 10;
var x;
true && (x = 10); // result will be 10

Related

How does this code work as conditional statements, why aren't there any "if" or "else if" statements?

Given the following problem that I need to solve about nested logic, I saw the following possible solution online but I hadn't seen code organized like this and can't help to figure it out. It looks like a different approach I hadn't seen to "if" and "else if" statements, so I would like to understand what's going on. Thank you.
let fine = 0;
const [actual, expected] = input.split('\n').map(item => {
const [day, month, year] = item.split(' ').map(Number);
return {
day,
month,
year
};
});
(
actual.year === expected.year &&
actual.month === expected.month &&
actual.day > expected.day
) && (fine = (actual.day - expected.day) * 15);
(
actual.year === expected.year &&
actual.month > expected.month
) && (fine = (actual.month - expected.month) * 500);
(actual.year > expected.year) && (fine = 10000);
console.log(fine);
}
The code takes advantage of something called short-circuit evaluation, which isn't unique to JavaScript. In a broad sense, short-circuit evaluation means only evaluating a boolean expression if it is necessary to determine the ultimate outcome. It also takes advantage of the fact that in JS, assignment operators act as expressions.
Here's an example of what I mean:
let x;
console.log(x = 2) // 2
What this means is that you can have an assignment expression at the end of a list of conditions to act as an if statement. Due to short circuit evaluation, the assignment expression will only be evaluated if the ultimate true/false value of the full expression is not predetermined by the conditions.
let x;
(false && x = 1) // does nothing, false && ___ = false
(true || x = 2) // does nothing, true || ___ = true
(true && x = 3) // sets x = 3, true && ___ evaluates ___
(false || x = 4) // sets x = 4, false || ___ evaluates ___
JavaScript has short-circuit boolean evaluation, and the code in your question uses that extensively.
Take for example:
a() && b(); // if (a()) b();
Because both a() and b() need to evaluate to a truthy value for the entire statement to be considered true, JavaScript will not evaluate b() if a() already evaluates to a falsy value.
Similarly:
c() || d(); // if (!c()) d();
Because only one of c() or d() needs to evaluate to a truthy value for the entire statement to be considered true, JavaScript will not evaluate d() if c() already evaluates to a truthy value.
This can be used to implement logical branching, much like an if-else structure, although in most cases it does adversely impact the code's readability.
Nothing big changes in your code.
Heare simple syntax with the conditional operation in javascript var varname = condition ? true part code : false part code.
let fine = 0;
const [actual, expected] = input.split('\n').map(item => {
const [day, month, year] = item.split(' ').map(Number);
return { day, month, year };
});
fine = (actual.year === expected.year && actual.month === expected.month && actual.day > expected.day) ? ((actual.day - expected.day) * 15) : 0;
fine = (actual.year === expected.year && actual.month > expected.month) ? ((actual.month - expected.month) * 500) : 0;
fine = (actual.year > expected.year) ? 10000 : 0;
console.log(fine);
Something more

Correctness of !args.value || args.value.length?

I'm reviewing this line of code. It has an expression that looks like this:
!args.value || args.value.length
For example suppose we do this:
let v = {};
console.log(!v.value); //logs true
console.log(v.value); //logs undefined
console.log(v.value.length); //Script wont run - cannot read property length of undefined
So even though value is undefined, we are proceeding to check that args.value.length (or undefined> is less than the constraint? So effectively we could be checking something like this ( IIUC ):
true throws
!undefined || undefined.length < 4
So I thought the purpose of the first check in the statement was to make sure that the undefined is actually defined?
So in other words it should be args.value && args.value.length? Or stated differently:
if args.value exists, then check the length of it?
Here's the entire snippet in context just for completeness:
if (isMinLength && (!args.value || args.value.length < args.constraints[0])) {
return eachPrefix + "$property must be longer than or equal to $constraint1 characters";
The < has higher precedence than ||:
if (isMinLength && (!args.value || (args.value.length < args.constraints[0]))) {
// ^ ^
So the condition matches if either args.value doesn't exist, or when its .length is too small.
At first its actually
!args.value || (args.value.length < args.constraints[0])
But you are right, the only difference to
args.value && args.value.length < args.constraints[0]
Is that the first always returns false while the second returns undefined if args.value is not defined. As you use that in an if statement, the outcome doesnt really matter.

One line of if..else if.. else statement

I tried to write one line if..elseif..else statement but it always goes in else if.
var x = "192.168.1.1";
x = x == ("google.com") ? ("true google.com") : (("yahoo.com") ? ("true yahoo.com") : ("192.168.1.1"));
console.log(x);
Is there something I am missing? Why does it always go in else if?
You missed the x == (""yahoo.com"") statement
var x = "192.168.1.1";
x = (x == "google.com") ?
"true google.com" :
(x == "yahoo.com") ?
"true yahoo.com" :
"192.168.1.1";
// --------------------------------------------^^^^^^^^^^^^^^^^------------------------------------
console.log(x);
But it will be more readable with if - else if - else statements. Don't make your code concise if it will decrease the readability.
Your ternary operation
x = x == ("google.com") ? ("true google.com") : (("yahoo.com") ? ("true yahoo.com") : ("192.168.1.1"));
can be thought of as if-else if-else block as follows:
if(x == ("google.com")) {
x = "true google.com";
}
else {
if("yahoo.com") {
x = "true yahoo.com"; //Always true since it is a non-empty string
}
else {
x = "192.168.1.1"
}
}
So since you are initializing x to "192.168.1.1", it obviously is not equal to the the string specified ("google.com") in the first condition (if block). So it moves on to the else block and evaluates the if condition inside the else block. This if block in turn only checks if a string literal "yahoo.com" is empty or not. Since it is not empty, the condition is satisfied.
For your purpose, you need to change that from if("yahoo.com") to x == if("yahoo.com"). However, once you make this change, it will always go to the else block because the first two conditions will never satisfy.
This does not answer the question
Why does it always go in else if?
but it could help with
Is there something I am missing?
Yes, you mis some clarity for further use and a clear pattern, how to get for a given string another string.
You could use an object, which is easy to maintain for the keyed values.
values = {
"google.com": "true google.com",
"yahoo.com": "true yahoo.com",
default : "192.168.1.1"
};
The call works with a default operator || (logical OR):
x = values[x] || values.default;
var x = "192.168.1.1",
values = {
"google.com": "true google.com",
"yahoo.com": "true yahoo.com",
default : "192.168.1.1"
};
x = values[x] || values.default;
console.log(x);

Javascript usage of && operator instead of if condition

What's the point of having this logical operator like this: r == 0 && (r = i);?
function do()
{
var r = 0;
var i = 10;
r == 0 && (r = i);
}
is this the same as:
if (r==0)
{
r=i;
}
What always helps me is translating it to words
var r = 0;
var i = 10;
r == 0 && (r = i);
translates to
set variable r to zero
set variable i to ten
if variable r equals zero AND the return of the following statement "set variable r to value of variable i"
do nothing, but r is now 10.
so in short, let's forget about 1 and 2.
In javascript the execution flow in a boolean comparisan is to stop execution of if statement parameters if any part from the && fails.
An boolean comparisan will execute from left to right.
1 == 1 && 2 == 3 && (r = i)
it will pass 1 == 1 fail on 2 == 3 and never reach the assigment operation.
Basically it's a shorthand for:
if(r == 0) {
r = i;
}
Simple yes r == 0 && (r = i);is same as
if (r==0)
{
r=i;
}
Just tested the speed of the code and the && is little bit faster (almost negligible).
Coming to the actual question, I found the place of using && instead of if us literally short hand code of later. However I never use the code as it highly kill the readability of code reader.
As docs says
Logical operators are typically used with Boolean (logical) values. When they are, they return a Boolean value.
But what we are seeing here is an assignment to the a variable based on other. Of course the code works but I believe, this is just a mis usage of the convention.
It is the same, in terms of logic and control flow.
It is shortening lines of code (code golf) by (ab)using short-circuit behavior.
The StackExchange page for code golf is https://codegolf.stackexchange.com.
For even shorter code, you could use a logical OR as default operator.
r = r || i;
Or
r || (r = i);
I've been reading some of the answers here and I've come up with this summary.
Short Summary
Condition on r: Assign i to r, in case r is null:
r = r || i
Or
r || (r = i)
Condition on i: Assign i to r, in case i is not null:
i && (r = i)
Or
r = i || r
More Examples
a || (Do Something) // Means: if `a` is `null`
!a || (Do Something) // Means: if `a` is **not** `null`
a && (Do Something) // Means: if `a` is **not** `null`
!a && (Do Something) // Means: if `a` is `null`
It is indeed the same, and a technique often used by minifiers to collapse code. In this case, you can even use an ! in order to do the if as you are comparing without typecheck:
!r && (r = i);
Or use an || operator for this assignment:
r = r || i;
If you want to keep your code clear, use an if tho.
Consider you have something to print only when r=0 and i=10. then && will be use full like.
if(r==0 && i==10){
console.log('its good practice')
}
if we use seperate, like
if(r==0){
if(i==10){
console.log('its bad practice')
}
}
what will you do if you have lots of condition to check.? i suggest you to use first one.

Javascript short circuiting in if statement

I am confused about the below if statement code. Not sure what it is exactly doing
if (this.props.filterURL && nextProps.filterURL !== this.props.filterURL) {}
Can someone please help me to understand this?
Is it a short-circuiting in if statement:
i.e
1- if first this.props.filterURL from left side is false then it will return false. 2- if first this.props.filterURL has a value then it will return true and the second variable nextProps.filterURL will be compared to this.props.filterURL on the right most of the statement?
Notes :
This short-circuiting is good for the performance, as it allows significant bits of calculations to be skipped.
The AND operator (&&) returns true if both expressions are true, otherwise it returns false.
DEMO
var x = 1;
var y = 5;
if (x > 0 && y < 6) { console.log(x) }; // true
if(x > 1 && y < 6) { console.log(x) }; // false
As suggested by nnnnnn in his comment, the first this.props.filterURL is checking for a truthy value, not for true specifically. If the property is not defined that is falsy, but if the value is null or 0 or an empty string those are all falsy too.
In case of AND operator it evaluates the second expression only if the first one is true.
In your case,
if (this.props.filterURL && nextProps.filterURL !== this.props.filterURL) {}
can be interpreted as if(expr1 && expr2)
where expr1= this.props.filterURL and expr2 = nextProps.filterURL !== this.props.filterURL
for first expression expr1 it evaluates whether it is not null or undefined...
for the second expression expr2 nextProps.filterURL !== this.props.filterURL it checks both the value and data type. So for example if you have both value as same 1234 but for one it is of type String and for another it is for number, this condition would be true.

Categories

Resources