So, I'm looking into writing a slightly more complex operation with logic operators in an if-else statement. I know I can do parentheses, and I know it's the better way of doing this, but I've gotten curious and so I'm going to ask. If I were to do something like this:
if (firstRun == true || selectedCategory != undefined && selectedState != undefined) {
//Do something
} else {
//Do something else
}
How will that be operated without the use of parentheses? I know there is an order of operations for logic operators, similar to PEMDAS, right? I'm curious if it'll be ran something like this:
firstRun == true || (selectedCategory != undefined && selectedState != undefined)
or maybe if the 'OR' operator takes precedence instead and it ends up going like:
(firstRun == true || selectedCategory != undefined) && selectedState != undefined
The full list would be nice, if you can find it somewhere, of the order of operations for this. Thanks!
My rule of thumb, which covers basically 99% of all use cases for conditional statements, is:
Grouping: ()
Member access . or [...]
Not: !
Comparison, e.g. < , >= , === , !=, ...
Logical AND &&
Logical OR ||
MDN gives you the exhaustive breakdown: JavaScript Operator Precedence
So for your example:
(firstRun == true || selectedCategory != undefined && selectedState != undefined)
equals
(firstRun == true) || ((selectedCategory != undefined) && (selectedState != undefined))
For anything more complex than the above mentioned cases, I would look into refactoring the code for readability's sake anyway!
There is a pretty good rule of thumb to this. Think of these operators as of mathematical ones:
AND is multiplication (eg. 0 * 1 = 0 => FALSE)
OR is adding (eg. 0 + 1 = 1 => TRUE)
When you remember this, all you have to know is that multiplication always comes before addition.
See this chart for precedence.
I'm not going to explain what happens because the next guy reading your code will think: "WTF? Does that do what it should?"
So the better solution is to wrap the terms in parentheses even if you know the precedence, applied it correctly and the code works
This follows the old wisdom that you shouldn't do everything you can just because you can do it. Always keep an eye on the consequences.
See Operator precedence.
&& is before ||, so your expression is equivalent to:
firstRun == true || (selectedCategory != undefined && selectedState != undefined)
It will be the first:
firstRun == true || (selectedCategory != undefined && selectedState != undefined)
As a general rule, in most programming languages, AND has higher precedence.
While logical operator precedence is not actually defined in the ECMAScript Specification, MDN does a pretty good job of it and even has a separate page for logical operators.
My concern I suppose, since logical operator precedence is not actually defined in the ECMAScript specification, each individual browser vendor can potentially be different (I'm talking to you, Internet Explorer!), so your mileage may vary.
In the event anyone wants to test this across different browsers, here's a test case fiddle: http://jsfiddle.net/HdzXq/
$(document).ready(function() {
function log(test) {
$('div#out').append($('<p />').text(test));
}
function testOperatorPrecedence() {
log('(false || false && false) === ' + (false || false && false).toString());
log('(false || false && true) === ' + (false || false && true).toString());
log('(false || true && false) === ' + (false || true && false).toString());
log('(false || true && true) === ' + (false || true && true).toString());
log('(true || false && false) === ' + (true || false && false).toString());
log('(true || false && true) === ' + (true || false && true).toString());
log('(true || true && false) === ' + (true || true && false).toString());
log('(true || true && true) === ' + (true || true && true).toString());
log('----------------------------');
log('(false || (false && false)) === ' + (false || (false && false)).toString());
log('(false || (false && true )) === ' + (false || (false && true)).toString());
log('(false || (true && false)) === ' + (false || (true && false)).toString());
log('(false || (true && true )) === ' + (false || (true && true)).toString());
log('(true || (false && false)) === ' + (true || (false && false)).toString());
log('(true || (false && true )) === ' + (true || (false && true)).toString());
log('(true || (true && false)) === ' + (true || (true && false)).toString());
log('(true || (true && true )) === ' + (true || (true && true)).toString());
}
testOperatorPrecedence();
});
Related
just have 2 question regarding JS conditional operator, is the below 2 expression valid?
1.
if(isUser && isUser === true || isGuest && isGuest === true){
//...
}
I am wondering do I have to add () to make it like and still have the same functioning:
if((isUser && isUser === true) || (isGuest && isGuest === true)){
//...
}
const items = list.orderList && list.orderList.isUser === true || list.orderList.isGuest ? list.items : [];
I am wondering do I have to add () to make it like and functioning the same as above conditional operator:
const items = list.orderList && (list.orderList.isUser === true || list.orderList.isGuest === true) ? list.items : [];
As per Operator Precedence in the MDN docs, logical AND takes precedence over logical OR. Therefore,
expression1 || expression2 && expression3
will evaluate to
expression1 || (expression2 && expression3)
Therefore,
isUser && isUser === true || isGuest && isGuest === true
naturally evaluates to
(isUser && isUser === true) || (isGuest && isGuest === true)
anyway, so you do not need parentheses..
But since, in your second example, you want to evaluate OR then AND, you do need parentheses for it to evaluate the way you require, as
list.orderList && list.orderList.isUser === true || list.orderList.isGuest
will evaluate to
(list.orderList && list.orderList.isUser === true) || list.orderList.isGuest
Task is to check whether string results true or false for following given condition:
If a letter a to z occurs it must have '+' before and after the particular letter
This works fine expect the case when '=' comes before or after the letter.
Why this condition is wrong for '=' ?
This code returns true for these strings
Thanks
function SimpleSymbols(str) {
var temp=str.split("")
if(temp.length==1 || temp.length==2 )
return false;
for(i=0;i<temp.length;i++){
if(temp[i]>='a' && temp[i]<='z'){
if(i===0 || i===(temp.length-1)||
(temp[i-1]!=='+' && temp[i+1]!=='+')){
return false;
}
}
}
return true;
}
The condition (temp[i-1]!=='+' && temp[i+1]!=='+') is only true if both the character before and after the letter are not pluses. If one of them is a plus sign the condition is false.
You need to change the logical and to an or operator: (temp[i-1]!=='+' || temp[i+1]!=='+')
Background: De Morgan's Laws
The original condition is that a letter is surrounded by plus signs:
temp[i-1] === '+' && temp[i+1] === '+'
In your if clause you test that this condition is not matched. So, the original condition becomes:
!(temp[i-1] === '+' && temp[i+1] === '+')
To transform this into a condition using not-equals, you need to apply De Morgan's Laws which basically say that a logical and becomes an or and vice-versa if you factor in a negation. This makes the resulting condition:
temp[i-1] !== '+' || temp[i+1] !== '+'
<!-- I think you should change the condition operator -->
function SimpleSymbols(str) {
var temp=str.split("")
if(temp.length==1 || temp.length==2 )
return false;
for(i=0;i<temp.length;i++){
if(temp[i]>='a' && temp[i]<='z'){
if(i===0 || i===(temp.length-1)||
(temp[i-1]!=='+' || temp[i+1]!=='+')){
return false;
}
}
}
return true;
}
Hint: check out these strings too, they all return true even though they should return false.
"+a4"
"1a+"
"%a+"
Let's simplify your condition:
str[i-1] !== '+' && str[i+1] !== '+'
is the same as
!(str[i-1] === '+' || str[i+1] === '+')
This makes it easier to see what you were really checking.
We can see now that the condition str[i-1] !== '+' && str[i+1] !== '+' returns true only if neither of those two characters are a +.
You want it to return true if at least one is not a +. So you should use this instead:
str[i-1] !== '+' || str[i+1] !== '+'
I re-wrote your code with this correct condition here:
function SimpleSymbols(str) {
if (str.length == 1 || str.length == 2) return false;
for (var i = 0; i < str.length; i++) {
if (str[i] >= 'a' && str[i] <= 'z') {
if (i === 0 || i === (str.length-1) || (str[i-1] !== '+' || str[i+1] !== '+')) {
return false;
}
}
}
return true;
}
Note: regular expressions can help out a lot with pattern-matching in strings like this.
E.g. your whole function would have simply become the regex:
function SimpleSymbols(str) {
return !str.match(/[^+][a-z][^+]/) && str.length > 2;
}
I have two if statements that'd like to turn into a ternary but I don't know how.
if (val === true && optval === 'car' || val === true && optval === 'truck' )view_list.style.display = 'none';
if (val === true && optval === 'buss' || val === true && optval === 'van')view_list.style.display = '';
Apart in hacks I won't mention, a ternary is used when you want to return a value in all cases.
If val isn't true, then you do nothing.
Therefore this can't be used here.
view_list.style.display =
(val === true && optval === 'car' ||
val === true && optval === 'truck' ) ?
'none' :
((val === true && optval === 'buss' ||
val === true && optval === 'van') ?
'' :
view_list.style.display ) ;
or more succinctly :
view_list.style.display =
(val === true && ( optval === 'car' || optval === 'truck' ) ) ?
'none' :
((val === true && ( optval === 'buss' || optval === 'van' ) ?
'' :
view_list.style.display );
The parentheses around the second conditional are optional.
Of course this is not really a good approach, and this answer should not be seen as an endorsement to this style of programming.
Because nobody has said it yet, switch
if (val === true)
switch (optval) {
case 'car':
case 'truck':
view_list.style.display = 'none';
break;
case 'buss':
case 'van':
view_list.style.display = '';
break;
}
Not what you were asking for, but as #dystroy said, this is not the best case for a ternary.
But you can still make it a bit more elegant. How about
var styleMapping = {
'car': 'none',
'truck': 'none',
'buss': '',
'van': ''
};
// Apparently val is always required in your example
if (val) {
view_list.style.display = styleMapping[optval];
}
This also has the benefit that refactoring and adding new styles is very easy without having to write much code. Just add one line in the mapping and you're done. And of course it's much more readable and closer to what you intend to do.
You don't really care about boolean logic, you just want to have a different style based on what optval is set to.
I've got an 'if' statement and just wanted to know if these are both valid (which I believe they are) and if so what is the difference?
var type;
var type2;
if ((type == 'BOS'|| type == 'BPS'|| type == 'BRS') && (type2 == 'BOS'|| type2 == 'BPS'|| type2 == 'BRS))
OR
if ((type == 'BOS') || (type == 'BPS') || (type == 'BRS') && (type2 == 'BOS') || (type2 == 'BPS') || (type2 == 'BRS'))
Which has the correct syntax and do they do anything differently? is there a way to shorten this statement?
Thanks
The two statements are different. Yes, they are both valid statements, syntactically, but logically they differ. Since the && operator has a higher precedence than the || in javscript,
the resulting logic will evaluate as follows in statement 2:
1) (type == 'BRS') && (type2 == 'BOS')
2) (type == 'BOS') || (type == 'BPS') || (result of 1) || (type2 == 'BPS') || (type2 == 'BRS')
While in statement 1:
1) (type == 'BOS'|| type == 'BPS'|| type == 'BRS')
2) (type2 == 'BOS'|| type2 == 'BPS'|| type2 == 'BRS')
3) (result of 1) && (result of 2)
var type1;
var type2;
var correct_value = {
BRS: 1,
BOS: 1,
BPS: 1
};
if( correct_value[type1] && correct_value[type2]) {
alert('ok');
}
else {
alert('not ok');
}
Both conditional statement are valid but the result may be different.
The first statement will evaluate the OR value in the first bracket, and then evaluate the OR value in the second bracket, and finally evaluate the AND operator.
The second statement will evaluate the AND first and then evaluate from left to right without specific precedence (as in the first one).
You have to know which one do you actually use to determine the best refactoring code for it.
See this link: Operator Precedence.
if(e.FN === ' ' && e.GN === ' ' && e.LN === ' ' && e.DB === ' '){
This condition is never evaluated at all. Is this the way to check if all the values are null.
Right now you are checking if those values are all equal to a Space. The === not only compares the values but ensures they are the same type. However, if e.FN is null both e.FN == ' ' and e.FN === ' " will always return false. I think what you want is
if(e.FN === null && e.GN === null && e.LN === null && e.DB === null)
or even better, if you don't care if they are null, undefined or 0 you could do
if(e.FN && e.GN && e.LN && e.DB)
try:
if(e.FN === null && e.GN === null && e.LN === null && e.DB === null){
To check if all the values are null you should do:
if(e.FN === null && e.GN === null && e.LN === null && e.DB === null){
if the first value is not null javascript doesn't evaluate other condition, because if the first condition is false it's not possible for all the conditions to be true.