Step 3: Comparison Operators and Conditionals

April 30, 2021

Boolean Data Type

So far, we have learned two data types: numbers and strings. In this section, we will be learning about a new data type called booleans.

A boolean is a true or a false value. Here is an example of a boolean.

const x = true;

Here, the variable x has a value true, which is of type boolean.

Boolean values are generated as a result of using comparison operators.

Comparison Operators

Comparison operators are operators that allow us to compare two values and generate a boolean value as a result. Here is a list of comparison operators:

  • > Bigger Than
  • < Smaller Than
  • === Equal
  • >= Bigger Than or Equal
  • <= Smaller Than or Equal
  • !== Not Equal

And here are some example usages of these Boolean operators:

console.log(10 > 3);
console.log(-10 < 0);
console.log("John" === "John");
console.log(10 >= 10);
console.log(10 <= 10);
console.log(42 !== 7);

All of these operations would result in a true value.

There is also the ! operator that inverts the value of a boolean result.

const myVariable = true;
console.log(!myVariable); // false

In the above example, !myVariable would be equivalent to false. That is because using ! in front of a boolean would invert the value of that boolean.

There are a couple of complexities that we need to be aware of regarding using comparison operators.

Equality Operator vs. Strict Equality Operator

There are two kinds of equality operators in JavaScript. The equality operator (== or !=) and the strict equality operator (=== or !==). We will almost always use the strict equality operator.

Equality operator can be misleading since it doesn't check the type of values that we are comparing. When using the equality operator, these two completely different values would appear to be the same:

console.log(10 == "10"); // true

This is extremely misleading. The numeric value 10 and the string value "10" are nothing alike. We will not get this result if we are to use the strict equality operator.

console.log(10 === "10"); // false

You should avoid using the equality operator like a plague and use the strict equality operator at all times. I can't remember the last time that I have used the equality operator. If we wanted to check to see if a number matches the string's value, there are other ways of going about it, like converting that number to a string or converting the string to a number (by using the parseInt function that we have learned about).

Comparing Fractional Numbers

In the example below, you might expect x and y to be equivalent. They are not.

const x = 0.1 + 0.2;
const y = 0.3;
const z = x === y;
console.log(z); // false

Computers use a binary number system to represent the values that we throw at them. Basically, everything is represented as a 0 or 1. This results in some loss of precision when the computer stores the results of fractional number operations. This causes issues such as above, where 0.1 + 0.2 is not equivalent to 0.3. This is a very common issue to be aware of when working with fractional numbers. There are a couple of workarounds for this issue. One is to check to see if two numbers are equivalent in the range of some threshold. Let's say the threshold for our error tolerance is 0.01 for the example above, which means that the numbers can slightly differ from each other but not more than 0.01. Here is how we would represent this idea in code.

const threshold = 0.01;

const x = 0.1 + 0.2;
const y = 0.3;
const z = Math.abs(x - y) < threshold;
console.log(z);

Math.abs is a function that converts the given input to an absolute value (meaning converts the given numeric value to a positive value). In the above example, we say that if the difference between two values is smaller than a threshold of our choice, then we accept that these two values are equivalent. They are not equivalent if their difference is greater than the threshold.

Another way of doing comparisons using fractional numbers would be to convert them to string and then compare. We haven't learned how to convert a value to a string yet, so we will not explore that option here.

Logical Operators

Logical operators allow us to build compound statements using more than one boolean value.

Imagine I told you that you would be happy if you took care of your health AND your finances. This means that you need to take care of both your health and finances to be happy. If you didn't do either one of them, it is not going to work out. This is the logic behind the AND (&&) operator in JavaScript. It returns true if both sides of the operation are true.

let isTrue = true && true;
console.log(isTrue); // true

isTrue = 10 === 10 && 10 !== 11;
console.log(isTrue); // true

let isFalse = true && false;
console.log(isFalse); // false

isFalse = false && true;
console.log(isFalse); // false

isFalse = false && false;
console.log(isFalse); // false

As we can see in the above example, both sides of the AND operator need to be true for the resulting operation to be true.

Now let's imagine I told you that you would be healthier if you improved your diet OR you started to exercise more. This means that you just need to do one of those things to see an improvement in your health. This is how the OR (||) operator works in JavaScript. It returns true as long as one of the values that we are comparing is true.

let isTrue = true || false;
console.log(isTrue); // true

isTrue = false || true;
console.log(isTrue); // true

let isFalse = false || false;
console.log(isFalse); // false

Conditional Statements

Boolean values might seem a bit useless on their own. They are great when used in conjunction with conditional statements. A conditional statement executes only if the given condition is true. It is skipped if the condition evaluates to false. This is very different from what we have been learning so far. Previously, the programs that we wrote were executed from top to bottom in a linear fashion. Using conditional statements, we can alter the flow of our program. We can skip or execute a certain part based on a condition.

An if statement is an example of a conditional statement. Here is how it works.

const myVariable = true;

if (myVariable) {
  console.log("This gets displayed only if `myVariable` is `true`");
}

An if statement consists of the if keyword, a condition written inside the parentheses next to it, and a body statement that is written inside curly braces. If the condition inside the parenthesis evaluates to true then the statement that is inside the curly braces gets executed. If not, it doesn't. Try changing the value of myVariable to false to see what happens.

We can append an else statement after the if statement.

const myVariable = true;

if (myVariable) {
  console.log("This gets displayed only if `myVariable` is `true`");
} else {
  console.log("This gets displayed if the `myVariable` is NOT `true`");
}

The else block of the conditional statement gets executed if the if statement doesn't. That is if the given condition evaluates to false. This is called an if-else statement.

This is basically (very basically, that is) how a login screen works.

const password = "1234";

if (password === "1234") {
  console.log("Welcome user");
} else {
  console.log("Login failed");
}

Conditional statements allow us to write extremely flexible programs because we can adjust our program's behavior based on some external input. Here, in this example, we are entering the value of the password ourselves, but there are more advanced ways to construct programs where we can capture the user input or fetch data into our program from other external sources.

else if Statement

There is also a statement called else if that we can use alongside if statements. It allows us to handle multiple conditions.

Here is a program that displays the grade of a student given their test score.

const score = 59;

if (score >= 90) {
  console.log("A");
} else if (80 <= score && score < 90) {
  console.log("B");
} else if (70 <= score && score < 80) {
  console.log("C");
} else if (60 <= score && score < 70) {
  console.log("D");
} else {
  console.log("F");
}

Since this functionality can be useful on multiple occasions, we might want to wrap it inside a function for reusability.

function getGrade(score) {
  let grade;

  if (score >= 90) {
    grade = "A";
  } else if (80 <= score && score < 90) {
    grade = "B";
  } else if (70 <= score && score < 80) {
    grade = "C";
  } else if (60 <= score && score < 70) {
    grade = "D";
  } else {
    grade = "F";
  }

  return grade;
}

let grade;
grade = getGrade(59);
console.log(grade);

grade = getGrade(71);
console.log(grade);

grade = getGrade(100);
console.log(grade);

if and if-else statements allow us to write very capable programs. We can adjust this function to handle invalid values to make it much more robust.

function getGrade(score) {
  if (score < 0 || score > 100) {
    console.log("You have entered an invalid value");
    return;
  }

  let grade;

  if (score >= 90) {
    grade = "A";
  } else if (80 <= score && score < 90) {
    grade = "B";
  } else if (70 <= score && score < 80) {
    grade = "C";
  } else if (60 <= score && score < 70) {
    grade = "D";
  } else {
    grade = "F";
  }

  return grade;
}

let grade;
grade = getGrade(59);
console.log(grade);

grade = getGrade(71);
console.log(grade);

grade = getGrade(100);
console.log(grade);

grade = getGrade(-10);
console.log(grade);

We have updated our function to display an error message and not to return a value when provided a score value below 0 or above 100. When we use the return statement without any value, JavaScript implicitly returns a value called undefined. An undefined is a built-in JavaScript value that represents the absence of a value.

We get the value undefined if we initialize a variable but don't assign a value. Or if a function doesn't return a value just like in our example.

let x;
console.log(x); // undefined

There is another value called null that is similar to undefined. Whereas undefined represents an implicit absence of a value, null represents the explicit absence of a value.

It is like the difference between saying "I don't know what the value is" (implicit) versus "there is no value here" (explicit).

const x = null;

Learning about null and undefined values provide a great segue for us to learn about truthy and falsy values.

Truthy and Falsy Values

We have learned that there are two Boolean values, true and false. There are also other values in JavaScript that are not Boolean but are considered to be like true or false when evaluated in a Boolean context. Think of the number 0. It is not a Boolean value. But if we were to use it in a conditional context it would evaluate as false because it is falsy. This means it is false-like but not precisely false.

const myVariable = 0;

if (myVariable) {
  console.log("This would NOT get displayed since `myVariable` is `0`");
}

Any non-zero number is truthy. They are true-like but not exactly true.

const myVariable = 42;

if (myVariable) {
  console.log("This would get displayed since `myVariable` is not zero");
}

null, undefined, 0, empty string (""), and NaN are examples of falsy values. Everything else is a truthy value.

Logical Operators Revisited

Previously we have learned about logical operators and their behavior. We have seen that the && operator returns true if both of the values that it operates on are true or it returns false. This is actually only true when we are using Boolean values. But we would notice that logical operators work differently when we provide other kinds of values.

const x = 42 && "hello world";
console.log(x); // displays "hello world"

Here is what's happening. There is this concept called short-circuit evaluation. An AND operation (an operation that uses &&) will short-circuit if the first (left-hand side) value is falsy. This means that it would simply evaluate to that value without looking at the rest of the operation. Otherwise, it would evaluate to the second (right-hand side) value.

An OR operation (an operation that uses ||) will short-circuit if the first value is truthy. Otherwise, it would evaluate to the second value.

Previously I have explained as if these operators would always result in a true or a false value. That is not entirely correct. They evaluate to one of the values that are being operated on, and their behavior is determined by short-circuit evaluation.

Summary

In this section, we have first learned about the Boolean data types of true and false. Then we have learned about comparison operators, which would result in Boolean values. We learned about some of the things that we need to be aware of when making comparisons. Like:

  • Making sure to use the strict equality operator.
  • Not directly comparing floating point numbers.

In addition to Boolean data types, we have also learned about two new values. These are null and undefined. They are used the signify an absence of a value.

We have the values true and false, but we have also values that are truthy and falsy. These are values that are not precisely Boolean but can be thought of as such.

We have then learned about logical operators and the concept of short-circuit evaluation.

The most important thing that we have learned about in this chapter is the conditional statements. Using if, else, and if else we can build programs that are much more capable than before.

Find me on Social Media