simplify if else statement - javascript

I have some functionality dependent on many conditions. All variables in conditional statements are boolean variables and the code is the following and I don't like it:
if (userHasMoreThanOneMarket && isOnlyMarketSelected || !userHasMoreThanOneMarket && userHasMoreThanOneAgency) {
if (isOnlyAgencySelected) {
//do case 1
} else if (noAgencySelected && isOnlyMarketSelected) {
//do case 2
}
}
Is there a way to make it more understandable and nice?

That's about as concise as you're going to get with JavaScript. I suppose if you really wanted to, you could create variables to store your binary options:
var multiMarketOneSelected = userHasMoreThanOneMarket && isOnlyMarketSelected;
var singleMarketMultiAgency = !userHasMoreThanOneMarket && userHasMoreThanOneAgency;
if (multiMarketOneSelected || singleMarketMultiAgency) {
if (isOnlyAgencySelected) {
//do case 1
} else if (noAgencySelected && isOnlyMarketSelected) {
//do case 2
}
}
Though I don't really know if you gain much readability from that.

Your code seems fine, but if you don't like it you could do something like this (note that the only improvement here is style, if you like it better):
function check(){
return {
valid: userHasMoreThanOneMarket && isOnlyMarketSelected || !userHasMoreThanOneMarket && userHasMoreThanOneAgency,
case: [
isOnlyAgencySelected,
noAgencySelected && isOnlyMarketSelected
]
};
}
var conditions = check();
if (conditions.valid) {
if (conditions.case[0]) {
//do case 1
} else if (conditions.case[1]) {
//do case 2
}
}

Some things I would try to make the code more readable:
Initialise the variables in a way that you don't have to negate them again. So !userHasMoreThanOneMarket becomes userHasOneMarket
isOnlyMarketSelected sounds redundant to me. And you are checking it in the outer if-clause and the inner again.
You probably have a lot of code above this code snippet to initialise and set all this boolean values. Try return; statements after each variable to get rid of if-conditions.
I hope this helps.

Related

If else if shortening

I can see there are so many related questions to this. Could not find anything specific addressing my query. Here is my question:
How can i shorten the below if else condition:
If (condition1)
{
If(condition2)
{
Logic A
}
}
Else if (condition3)
{
Logic A
}
One way i could come up was as below:
If (condition1 && condition2 || !condition1 && condition3)
{
Logic A
}
Just wondering if there is a better way of doing it?
In this case optimization is important only from readability point of view. From OP examples I would prefer original one, because it easier to follow for developer/reader who didn't write this code.
We execute one action or do nothing based on conditions, so I would wrap every condition chain which leads to the execution into the method with descriptive name and used them with or operator.
// condition 1 = customer.persisted
// condition 2 = bonuses.has(customer.id)
// condition 3 = promotionCodes.has(customer.promotionCode)
function whenExistingCustomerWithBonus() {
return customer.persisted && bonuses.has(customer.id);
}
function whenGuestCustomerWithPromotionCode() {
return customer.persisted === false && promotionCodes.has(customer.promotionCode);
}
// Usage
if (whenExistingCustomerWithBonus() || whenGuestCustomerWithPromotionCode()) {
// execute logic A
}
you can do this
(condition1 && condition2 || !condition1 && condition3) ? logic(a) : logic(b)
Its called Ternary operator, It would make your code shorter and you can also use it to set a variable, for example
const isTrue = 4 > 3 ? true : false
There are some aspects that you must keep in mind.
It's possible that a shorter code be faster in some script languages (like JavaScript, PHP...).
But it worth? Is your if inside a loop long enough to make any difference in your code execution time?
Do your shortened code makes easier or harder to understand your code? Sometimes joining some if conditions inside a boolean logic makes it easier to understand, but sometimes it's so complicated that is very hard to understand.
sometimes its possible to simplify (note the use of the word 'simplify' instead of 'shorten') conditional logic by reversing it, or by delegating logic to other functions, or a combination of both:
given this:
function performLogic() {
if (condition a) {
if (condition b) {
logic 1
}
} else {
logic 1
}
}
let's try to think about this in reverse:
function performLogic() {
if (!condition a) logic 1
else if (conditoin b) logic 1
}
keep in mind this kind of refactor will not always be possible, and i also advise you to write unit tests for the logic to ensure that the end result remains the same.
It can also sometimes be simplified further depending on the logic in the function. many times we can replace conditional logic with guard clauses like this:
function getSomeValue() {
if (condition a) {
if (condition b) {
... do some logic
return someValue;
}
}
}
this can be changed to
function getSomeValue() {
if (!condition a) return;
if (!condition b) return;
... do some logic
return someValue;
}

Exit from if block in Javascript

I want to exit from the below if block in Javascript. if I return, then it does not check for the next if condition. How do I do that?
if ($('#id1').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
//break from #id1
}
else{
//something
}
$("#abc").html(somthing)
}
if ($('#id2').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
//break from #id2
}
else{
//something
}
}
Super late to the party, but for folks from search, you can use something called labeling. It's not good practice, but in rare cases that can be applied. Basically you can assign a name to the if statement that you want to break from. And anywhere in statement call break from specified name.
Code example:
my_if: if (condition) {
// do stuff
break my_if;
// not do stuff
}
in your particular case:
id1: if ($('#id1').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
break id1;
}else{
//something
}
$("#abc").html(somthing)
}
More about labeling can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label#Syntax
Even later to the party... Typically in such situations, I use a combination of if and do...while as follows...
if ( condition ) do {
// processing
if ( exit_condition ) break;
// more processing...
} while ( false );
Thus, when the break is encountered, it applies to the do...while loop, and processing continues after the while, effectively breaking out of the outer if statement...
All your code after if(isNaN(yester_energy) || yester_energy == 0) is in else block, so it'll not be executed if your data matches this if. And you just don't need anything else.
Also, if you want to check if variable got NaN value, then use isNaN() function. You can't just compare it.
Use switch statment,
switch(n)
{
case 1:
execute code block 1
break;
case 2:
execute code block 2
break;
default:
code to be executed if n is different from case 1 and 2
}
you can use function and pass command
function iff(condition){
if(condition ==0) return;
console.log("other commands")
}
iff(0);
iff(1)
Don't Use Labeling
You can do labeling as the other answer suggests, but it smells odds and it will definitely come up in code review. It will confuse readers of your code and increase the maintenance burden of your codebase.
Answer
Best is to refactor (extract out) the code inside the if-statement into a separate function that you can then return from. In addition to allowing you to exit from the code block early, it also makes your code more modular and readable.
Example (based on OP)
if ($('#id1').length > 0) {
ifInner(yester_energy)
$("#abc").html(somthing) // [sic]
}
if ($('#id2').length > 0) {
ifInner(yester_energy)
}
// Rename to something more descriptive.
function ifInner(yester_energy) {
if (yester_energy == "NaN" || yester_energy == 0){
// Break out.
return;
}
else {
// something
}
}
Adding another answer to the pool, in many cases using a try catch makes perfect sense:
if(something is allowed) {
try {
if(missing requirements) throw 'missing requirements'
//do your stuff;
}
catch {
//you may do logging and issue warning here
}
}

How can I check if an array is set and contains a value at the same time?

I need to check if ['pk'] is available in the first item in an array, and only then do some stuff. The array is not always populated, so I am ending up with a block of code that feels a little bit bloated.
How can I make this code shorter and nicer? I'm sure Javascript have a way to do this better... (without having a lot of errors in the console while the array is empty...)
var $selectedItem = $scope.selectedItem[0] || null;
if($selectedItem) {
var $selectedPK = $selectedItem['pk'];
}
if($selectedPK) { ... }
Since there's no further checking if the first part of the boolean and condition is false, this is much more concise:
if ($selectedItem && $selectedItem['pk']) {
...
}
I think you should be able to make the assignment in the condition right away:
if ($selectedItem && ($selectedPk = $selectedItem['pk'])) {
...
}
Sounds like you could at least combine the two
var $selectedItem = $scope.selectedItem[0] || null;
if($selectedItem) {
var $selectedPK = $selectedItem['pk'];
if($selectedPK) {
...
}
}
Here's one more ;)....
if ($scope.selectedItem[0] && $scope.selectedItem[0].pk!==undefined) {
// do stuff
}

Call break in nested if statements

I have the following situation:
IF condition THEN
IF condition THEN
sequence 1
ELSE
break //?
ENDIF
ELSE
sequence 3
ENDIF
What is the result of the break statement? Does it break the outer if statement? Because this is what I actually need.
If you label the if statement you can use break.
breakme: if (condition) {
// Do stuff
if (condition2){
// do stuff
} else {
break breakme;
}
// Do more stuff
}
You can even label and break plain blocks.
breakme: {
// Do stuff
if (condition){
// do stuff
} else {
break breakme;
}
// Do more stuff
}
It's not a commonly used pattern though, so might confuse people and possibly won't be optimised by compliers. It might be better to use a function and return, or better arrange the conditions.
( function() {
// Do stuff
if ( condition1 ) {
// Do stuff
} else {
return;
}
// Do other stuff
}() );
no it doesnt. break is for loops, not ifs.
nested if statements are just terrible. If you can avoid them, avoid them. Can you rewrite your code to be something like
if (c1 && c2) {
//sequence 1
} else if (c3 && c2) {
// sequence 3
}
that way you don't need any control logic to 'break out' of the loop.
But there is switch-case :)
switch (true) {
case true:
console.log("Yes, its ture :) Break from the switch-case");
break;
case false:
console.log("Nope, but if the condition was set to false this would be used and then break");
break;
default:
console.log("If all else fails");
break;
}
In the most languages, break does only cancel loops like for, while etc.
To make multiple checking statements more readable (and avoid nested ifs):
var tmp = 'Test[some.email#somewhereouttherebutnothere.com]';
var posStartEmail = undefined;
var posEndEmail = undefined;
var email = undefined;
do {
if (tmp.toLowerCase().substring(0,4) !== 'test') { break; }
posStartEmail = tmp.toLowerCase().substring(4).indexOf('[');
posEndEmail = tmp.toLowerCase().substring(4).indexOf(']');
if (posStartEmail === -1 || posEndEmail === -1) { break; }
email = tmp.substring(posStartEmail+1+4,posEndEmail);
if (email.indexOf('#') === -1) { break; }
// all checks are done - do what you intend to do
alert ('All checks are ok')
break; // the most important break of them all
} while(true);
Javascript will throw an exception if you attempt to use a break; statement inside an if else. It is used mainly for loops. You can "break" out of an if else statement with a condition, which does not make sense to include a "break" statement.
JSFiddle
Actually there is no c3 in the sample code in the original question. So the if would be more properly
if (c1 && c2) {
//sequence 1
} else if (!c1 && !c2) {
// sequence 3
}
I had a similar problem today and found refactoring the conditional logic into a separate function to help.
I find it more readable than the labels and people are more comfortable with return than break. Inline functions are similar but the indentation can get a bit confusing.
In your case it would look like this.
function doThing() {
checkConditions();
// Rest of the code here
}
function checkConditions() {
if (c1) {
if (c2) {
return do1();
else {
return;
}
} else {
return do3();
}
}
Just remove the break. since it is already inside first if it will not execute else. It will exit anyway.
You need that it breaks the outer if statement. Why do you use second else?
IF condition THEN
IF condition THEN
sequence 1
// ELSE sequence 4
// break //?
// ENDIF
ELSE
sequence 3
ENDIF
sequence 4

is there a shorter way for this condition?

if (form.a.value !=""&&form.b.value!="" &&form.c.value !="")
is there a shorter way for this condition?
Javascript is weakly-typed so you can treat empty string as boolean false, so the following code should work:
if (form.a.value && form.b.value && form.c.value) {
However I don't know why would you want to change that code. Actually it's quite clear and verbose.
If you have only three fields(or less), you can leave it as is. If you have more(or unknown) number of fields to check, create an array of fields to check and do the checks in loop in separate function for better maintainability. Something like this:
if(!Empty([form.a,form.b,form.c]))
{
...
}
function Empty(elements)
{
for(var i=0;i<elements.length;i++)
{
if(elements[i].value)
return false;
}
}
there are lazy ways :)
if(form.a.value + form.b.value + form.c.value != "" )
if(form.a.value.length + form.b.value.length + form.c.value.length != 0 )
if(!form.a.value && !form.b.value && !form.c.value)

Categories