Conditionals

Understanding Booleans

To understand conditionals (if, else if, else blocks) in JavaScript, you'll need a solid understanding of booleans first.

true and false

Simply put, a Boolean only has two values it can be - true or false. These are reserved keywords in JavaScript and must be spelled/capitalized (not capitalized at all) correctly.

Examples:

var myBool = false;
var isThisASimpleConcept = true;

Conditions

The concept of conditions are pretty straight-forward, since they're actually part of our every day life (usually without realizing it, we're evaluating conditions just about every waking minute of our life).

For example, you probably evaluate a condition when you first wake up. You look at a clock to see what time it is, and if you woke up on time, you'll get ready at a leisurely pace, eat breakfast, etc. Otherwise (else) you'll rush to get ready.

The condition in this example is the time on the clock compared to the time you wish it were. In JavaScript, this might look like the following:

if (currentTime <= wakeUpTime) {
    beLeisurely();
    eatBreakfast();
} else {
    rushOutTheDoor();
}

Anatomy of the conditional statement

You'll always start a conditional block with an if statement, followed by parentheses and curly braces:

if (condition) {
    // thing to do;
}

The computer's job is to check the part inside the parentheses and turn it into a boolean, either true or false.

If it is able to turn the condition into true, it will run the code inside the if block curly braces. If it turns it into a false, it won't.

Comparison Operators

We usually don't know ahead of time the values of the things we're comparing. So we use comparison operators and equality operators to check the current status of different variables so that our program can make the correct decision on which code it should run.

Equality/inequality operators
  • === checks that the operand on the left side is the same value and same data type as the operand on the left
    • 1 === 1 will evaluate to true
    • "1" === 1 will evaluate to false
  • !== checks that the operand on the left is NOT the same value or is not the same type as the operand on the right
    • 2 !== 2 evaluates to false
    • "2" !== 2 evaluates to true
Comparison operators
  • > returns true if the left operand is greater than the right operand
    • 1 > 2 return false
    • 20 > 10 returns true
  • < returns true if the left operand is less than the right operand
    • 3 < 4 returns true
  • >= and <= return true if the left is greater than or equal to or less than or equal to the right, respectively.
    • 5 >= 5 returns true
    • 6 <= 7 returns true
A (kind of) practical example:

For example, let's say we only want to allow children under 18 to use our website. The first thing we do when the page loads is pop up a box asking the user's age. Then, if the number they input is less than 18, we continue to load the site. Otherwise (else) we tell them they're too old to be here.

var age = parseInt(prompt("What is your age?"));

if (age <= 17) {
    // Allow the user in
} else {
    // Don't allow the user in
}
"Truthy" vs. "Falsey"

Sometimes in your code the computer can't simply turn a value into a boolean directly. If it sees if(true || false)... it knows how to turn the true || false into a boolean (true). But what if you have: if (42) {...} ?

The terms "truthy" and "falsey" refer to values that the computer can infer true or false from, even if they aren't booleans. Remembering what is "truthy" and what is "falsey" is pretty straight forward.

"Falsey" values in JavaScript:

  • false (naturally)
  • 0
  • "" (empty string)
  • null
  • undefined
  • NaN (Not a Number)

"Truthy" values in JavaScript:

  • Everything else
Examples:
var myArray = [];

if(myArray.length) {
    // won't run because myArray.length is 0, and that is a falsey value.
}

if (myArray) {
    // WILL run, because an empty array isn't one of the falsey values.
}

Logic operators

Sometimes we need to compare multiple things before knowing we want to run a certain block of code. Let's say, for example, that we created a website only for people named "Felix" who are older than 12 years old. As such, when the user creates their account we only want to allow them to create their account if their first name is "Felix" AND if their age is greater than or equal to 12. We need a way to combine comparisons, and that's where logic operators come in to play.

And (&&)

The double ampersand (&&) requires that the value on the left AND the value on the right of the && both evaluate to true in order for the whole expression to be considered true. As such:

  • false && false evaluates to false
  • false && true evaluates to false
  • true && false evaluates to false
  • true && true is the only one that evaluates to true

So, for example:

(1 > 3) && (false);  // false
(5 < 3) && (true);  // false
(1 < 3) && (false);  // false
(1 < 3) && (true);  // true

Advanced reading about && - The above explanation of the && operator will help you understand about 99.9% of the &&s you see. If this is your first time learning this stuff, feel free to move on.

However, there's a little more to the && operator. What it really does, rather than evaluate both sides to a true or false is it returns the first value if it is falsey and stops evaluating the rest of the expression, OR it will return the second value if the first value is truthy.

true && true => true (we knew this)
4 && 5 => 5 (Because 4 is a truthy value, the && returns the second value, which is 5, a truthy value. So `if(4 && 5){...}` will pass the conditional test
0 && 5 => 0 (First value is falsey, so it returns that value immediately, and conditionals using this will fail)
"" && false => "" (empty string is also falsey; conditionals fail)

This concept can be particularly useful in assuring that a function or method exists before trying to call it. Rather than typing:

if (person.speak !== undefined) {
    person.speak();
}

You can instead just do:

person.speak && person.speak();

If person.speak is undefined, it will stop evaluating that expression and not evaluate the method call. If it is truthy, it will call the method from the second part of the statement.

If that didn't make any sense to you, don't worry about it. Revisit this page at a later time and it might start to click.


Or (||)

The double pipe (||) allows either the value on the left OR the value on the right of the || to evaluate to true in order for the whole expression to be considered true. As such:

  • true || true evaluates to true
  • false || true evaluates to true
  • true || false evaluates to true
  • false || false is the only one that evaluates to false

So, for example:

(1 > 3) || (false);  // false
(5 < 3) || (true);  // true
(1 < 3) || (false);  // true
(1 < 3) || (true);  // true
Not (!)

Any expression or simple boolean can be reversed with the ! ("not") operator. For example:

console.log(!true);  // false
console.log(!false);  // true
console.log(!true || false);  // false
console.log(!(1 > 3) || !true);  // ==> !false || !true ==> true || false ==> true

Order of operations

It's important to note that the logical operators will execute in a pre-determined order of operations, similar how +, -, *, ÷, etc. in math have an order of operations.

There is a long list of point values associated with operations which you can find on MDN's Operator Precedence Table, but here are the ones we're most concerned with when talking about conditions:

  1. Grouping using parentheses - ()
  2. Not operator - !
  3. Logical And - &&
  4. Logical Or - ||

Here are some examples to illustrate the importance of understanding the order of operations.

!true || true;  // ==> false || true == > true
!(true || true); // ==> !(true) ==> false
!(!false && (true || false) || !(false || false));  // ==> !(true && true || !(false)) ==> !(true || false) ==> !true ==> false
Example

In our above example about the website where we only want to allow people whose name is Felix AND who is 12 or older, we could find ourselves writing something like the following:

var age = parseInt(prompt("What is your age?"));
var name = prompt("What is your name?").toLowerCase();

if (age <= 12 && name === "felix") {
    // Welcome!
} else {
    // Go away!
}

Switch statements

If you find yourself wanting to write a long chain of if, else if, else if, else if, else if etc. statements, you can shorten and simplify your chain by using a switch statement.

switch looks at a variable and tests it against a number of "cases". If the variable matches the case, it executes the code inside the case: block. It's important to use break after each case unless you want it to continue checking other cases as well.

You also will always want to add a default case at the end to act as an else, in case all of the above cases don't match.

switch (mood_ring) {
	case ‘blue’:
		mood = ‘calm’;
		break;
	case ‘red’:
		mood = ‘excited’;
		break;
	default:
		mood = ‘dead’;
}

Ternary operator

The ternary operator gives us a way to shorten a common if(){} block:

if (moodRing == "blue") {
    mood = "calm";
}

It works like this:

variableToSet = (conditionToCheck) ? <value if the condition is true> : <value if the condition is false>

Using the ternary operator (?) we can shorten this to:

mood = (moodRing === "blue") ? "calm" : mood;

What's the deal with == vs. ===?

First of all, as a general rule, you should always plan on using === instead of ==.

Both == and === will check to make sure the value of the two operands are the same. The difference is that === will also check to make sure the type of the two operands are the same. == on the other hand will attempt to coerce the two operands into the same data type. Since this can have some strange side effects, it's always best to use === and be sure you're getting a correct equality.

// Double equals (==)
"0" == 0  // true
"" == "0" // false
0 == ""   // true

false == undefined  // false
false == null       // false
null == undefined   // true

// Triple equals (===)
"0" == 0  // false
"" == "0" // false
0 == ""   // false

false == undefined  // false
false == null       // false
null == undefined   // false

As you can see, the === behaves more like you'd expect it to, without relying on JavaScript to do too much of your job as a developer for you. (Like making sure types are equal before comparing them).