JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.
In this article, we’ll look at the best practices for writing boolean expressions with JavaScript.
Use Decision Tables to Replace Complicated Conditions
If we have lots of boolean expressions to check for, we should use a lookup table to let us get the value from it in a shorter way.
For instance, instead of writing:
const findDayOfWeek = (val) => {
if (val === 0) {
return 'Sunday'
} else if (val === 1) {
return 'Monday'
} else if (val === 2) {
return 'Tuesday'
} else if (val === 3) {
return 'Wednesday'
} else if (val === 4) {
return 'Thursday'
} else if (val === 5) {
return 'Friday'
} else if (val === 6) {
return 'Saturday'
}
}
we instead write:
const dayMap = {
0: 'Sunday',
1: 'Monday',
2: 'Tuesday',
3: 'Wednesday',
4: 'Thursday',
5: 'Friday',
6: 'Saturday',
}
As we can see, it’s much shorter, and they do the same thing.
Forming Boolean Expressions Positively
Boolean expressions should be formed positively so that we don’t have to deal with double negatives.
For instance, if we have the following:
if (!ok) {
// do something
} else {
// do something else
}
We should write:
if (ok) {
// do something else
} else {
// do something
}
We flip the cases around.
They’re both the same, but the second one is much easier to read.
Apply DeMorgan’s Theorems to Simplify Boolean Tests with Negatives
DeMorgan’s Theorem states that the following:
!(a && b)
is the same as:
!a || !b
and:
!(a || b)
is the same as:
!a && !b
Therefore, we can use it to simplify these kinds of boolean expressions by applying the negation to all expressions.
Using Parentheses to Clarify Boolean Expressions
If we have complex boolean expressions, then we should clarify them by grouping them with parentheses.
So instead of writing expressions like:
a === b > c === d
We write:
(a === b) > (c === d)
This way, we know how they’re going to be evaluated when we run the code.
Short-Circuit Evaluation
JavaScript evaluates boolean in a short-circuit manner. This means that it’ll stop at the first expression evaluates to true
if it’s an or expression.
If it’s an and expression, it stops at the first false
expression.
Expressions are checked from left to right.
Therefore, we should make sure that we have expressions in the right order.
For instance, if we have:
if (((numerator / denominator) < MAX_VALUE) && (denominator !== 0)) {
//...
}
Then we can potentially be dividing by 0 in the first boolean expression since the denominator !== 0
check comes after the (numerator / denominator) < MAX_VALUE
check.
Therefore, we should reverse that so we check that the denominator
isn’t 0 before we divide numerator
by denominator
.
We should make sure the order of the expressions actually makes sense.
Writing Numeric Expressions in Number-Line Order
Writing expressions in number line order makes them easier to read.
Our brains expect numbers to go in order, so we should write our expressions in such order.
For instance, we can write the following:
1 < val && val < 10
instead of:
val < 10 && 1 < val
It just makes more sense to have them in number line order.
Compare Logical Variables Implicitly
We don’t need to compare boolean variables directly with true
or false
.
For instance, we write:
while (!done) {
//...
}
instead of:
while (!done === true) {
//...
}
As the part after !done
is redundant.
Compare Numbers to 0
If we compare numbers to 0, then we should write that out explicitly.
For instance, we should write:
while (amount !== 0) {
//...
}
Also, make sure that we’re using !==
or ===
to compare inequality and equality respectively.
Put Constants on the Left Side of Comparisons
Putting constants on the left side of comparisons lets us avoid accidentally assigning values to them.
For instance, instead of writing:
if (MIN_D0NUTS === i) {
//...
}
is better than:
if (i === MIN_D0NUTS) {
//...
}
As it avoids any accidental assignments.
Conclusion
We can make our lives easier by avoiding double negatives and nested boolean expressions.
Also, we should make sure that we have expressions in the correct order so that preconditions are evaluated first.