facebook google plus twitter
Webucator's Free JavaScript Tutorial

Lesson: Conditionals and Loops

Welcome to our free JavaScript tutorial. This tutorial is based on Webucator's Introduction to JavaScript Training course.

In this lesson, you will learn how to work with conditionals and loops.

Lesson Goals

  • Learn to write if - else if - else blocks.
  • Learn to write switch / case blocks.
  • Learn to work with loops in JavaScript.

Conditionals

There are two types of conditionals in JavaScript:

  1. if - else if - else
  2. switch / case

if - else if - else Conditions

Syntax

if (conditions) {
  statements;
} else if (conditions) {
  statements;
} else {
  statements;
}

Like with functions, each part of the if - else if - else block is contained within curly brackets ({}). There can be zero or more else if blocks. The else block is optional.

Comparison Operators
Operator Description
== Equals
!= Doesn't equal
=== Strictly equals
!== Doesn't strictly equal
> Is greater than
< Is less than
>= Is greater than or equal to
<= Is less than or equal to

Note the difference between == (equals) and === (strictly equals). For two objects to be strictly equal they must be of the same value and the same type, whereas to be equal they must only have the same value. See the code samples below:Strictly Equal

Notice that 0 is equal to, but not strictly equal to, an empty string. Both these values are falsy, meaning that when they are treated as Booleans, they are considered to be false. More on this soon.

It is almost always better to use the strictly equals operator (===) and the corresponding doesn't strictly equal operator (!==) as these help avoid unanticipated errors.

Logical Operators
Operator Description
&& and (a == b && c != d)
|| or (a == b || c != d)
! not !(a == b || c == d)

The example below shows a function using an if - else if - else condition.

Code Sample:

ConditionalsAndLoops/Demos/if-else-if-else.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../normalize.css">
<link rel="stylesheet" href="../styles.css">
<script>
  function checkAge(){
    var age = prompt("Your age?", "") || "";
    
    if (age >= 21) {
      alert("You can vote and drink!");
    } else if (age >= 18) {
      alert("You can vote, but can't drink.");
    } else {
      alert("You cannot vote or drink.");
    }
  }
</script>
<title>JavaScript Conditionals Demo</title>
</head>
<body>
<main>
  <h1>JavaScript if - else if - else Demo</h1>
  <h2>Age Check</h2>
  <button onclick="checkAge()">Age Check</button>
</main>
</body>
</html>

Code Explanation

The display of the page is shown below:if-else if-else 1

When the user clicks on the Age Check button, the following prompt pops up:if-else if-else 2

After the user enters his age, an alert pops up. The text of the alert depends on the user's age. The three possibilities are shown below:if-else if-else 3 if-else if-else 4 if-else if-else 5

Compound Conditions

Compound conditions are conditions that check for multiple things. See the sample below:

if (age > 18 && isCitizen) {
  alert("You can vote!");
}

if (age >= 16 && (isCitizen || hasGreenCard)) {
  alert("You can work in the United States");
}

Short-circuiting

JavaScript is lazy (or efficient) about processing compound conditions. As soon as it can determine the overall result of the compound condition, it stops looking at the remaining parts of the condition:Short Circuiting

Short-circuiting is useful for checking that a variable is of the right data type before you try to manipulate it.

To illustrate, take a look at the following sample:

Code Sample:

ConditionalsAndLoops/Demos/password-check-broken.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../normalize.css">
<link rel="stylesheet" href="../styles.css">
<script>
  var userPass = prompt("Password:", ""); //ESC here causes problems
  var pw = "xyz";
</script>
<title>Password Check</title>
</head>
<body>
<main>
  <script>
    if (userPass.toLowerCase() === pw) {
      document.write("<h1>Welcome!</h1>");
    } else {
      document.write("<h1>Bad Password!</h1>");
    }
  </script>
</main>
</body>
</html>

Code Explanation

Everything works fine as long as the user does what you expect. However, if the user clicks on the Cancel button when prompted for a password, the value null will be assigned to userPass. Because null is not a string, it does not have the toLowerCase() method. So the following line will result in a JavaScript error:

if (userPass.toLowerCase() === pw)

You can see the error in Chrome DevTools Console:Password Check Error

This can be fixed by using typeof (described below) to first check if userPass is a string as shown in the sample below:

The typeof Operator

The typeof operator is used to find out the type of a piece of data. The screenshot below shows what the typeof operator returns for different data types: The typeof Operator

Code Sample:

ConditionalsAndLoops/Demos/password-check.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../normalize.css">
<link rel="stylesheet" href="../styles.css">
<script>
  var userPass = prompt("Password:", "");
  var pw = "xyz";
</script>
<title>Password Check</title>
</head>
<body>
<main>
  <script>
    if (typeof userPass === "string" && userPass.toLowerCase() === pw) {
      document.write("<h1>Welcome!</h1>");
    } else {
      document.write("<h1>Bad Password!</h1>");
    }
  </script>
</main>
</body>
</html>

Code Explanation

Now, if the user presses Cancel and userPass gets null, this check will fail: typeof userPass === "string". Because the if condition uses && requiring that both conditions are true for the whole statement to be true, there is no reason to check the second condition if the first condition is false. So, JavaScript short circuits, meaning it immediately returns false without wasting time checking the second condition.

Short circuiting also works with or conditions (e.g., if (a or b). In this case, the whole statement is true if either side of the or condition is true. So, if a is true, there is no reason to check b. JavaScript will short circuit and return true.

Switch / Case

Syntax

switch (expression) {
  case value :
    statements;
  case value :
    statements;
  default :
    statements;
}

Like if - else if - else statements, switch / case statements are used to run different code at different times. Generally, switch / case statements run faster than if - else if - else statements, but they are limited to checking for equality. Each case is checked to see if the expression matches the value.

Take a look at the following example:

Code Sample:

ConditionalsAndLoops/Demos/switch-without-break.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../normalize.css">
<link rel="stylesheet" href="../styles.css">
<script>
  var quantity = 1;
  switch (quantity) {
    case 1 :
      alert("quantity is 1");
    case 2 :
      alert("quantity is 2");
    default :
      alert("quantity is not 1 or 2");
  }
</script>
<title>Switch</title>
</head>
<body>
<main>
  <p>Nothing to show here.</p>
</main>
</body>
</html>

Code Explanation

When you run this page in a browser, you'll see that all three alerts pop up, even though only the first case is a match.Switch w/o Break 1 Switch w/o Break 2 Switch w/o Break 3That's because if a match is found, none of the remaining cases are checked and all the remaining statements in the switch block are executed. To stop this process, you can insert a break statement, which will end the processing of the switch statement.

The corrected code is shown in the example below.

Code Sample:

ConditionalsAndLoops/Demos/switch-with-break.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../normalize.css">
<link rel="stylesheet" href="../styles.css">
<script>
  var quantity = 1;
  switch (quantity) {
    case 1 :
      alert("quantity is 1");
      break;
    case 2 :
      alert("quantity is 2");
      break;
    default :
      alert("quantity is not 1 or 2");
  }
</script>
<title>Switch</title>
</head>
<body>
<main>
  <p>Nothing to show here.</p>
</main>
</body>
</html>

Code Explanation

The following example shows how a switch / case statement can be used to decide what math operation to perform:

Code Sample:

ConditionalsAndLoops/Demos/do-math.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../normalize.css">
<link rel="stylesheet" href="../styles.css">
<script>
  function doMath(operator) {
    var n1 = parseFloat(document.getElementById('n1').value);
    var n2 = parseFloat(document.getElementById('n2').value);
    var result;
    switch (operator) {
      case "+":
        result = n1 + n2;
        break;
      case "-":
        result = n1 - n2;
        break;
      case "*":
        result = n1 * n2;
        break;
      case "/":
        result = n1 / n2;
        break;
      default:
        alert("Bad operator");
    }
    alert(n1 + operator + n2 + '=' + result);
  }
</script>
<title>doMath</title>
</head>
<body>
<main>
  <label for="n1">First Number:</label>  <input id="n1">
  <label for="n2">Second Number:</label>  <input id="n2">
  <button onclick="doMath('+')">Add</button>
  <button onclick="doMath('-')">Subtract</button>
  <button onclick="doMath('*')">Multiply</button>
  <button onclick="doMath('/')">Divide</button>
</main>
</body>
</html>

Code Explanation

Use Case for switch Without break

In most cases, you will include break statements in your switch conditions; however, there are cases when it makes sense to continue to execute all the subsequent statements in a switch condition after a match has been found. Consider the following, in which permissions are being added to an array based on a user's role:Use Case for switch without break

SuperAdmin will get all permissions. Admin will get update, create, and read permissions. Contributor will get create and read permissions. All others will only get read permissions.

Order of Conditions

In conditional statements it's generally a good practice to test for the most likely cases/matches first so the browser can find the correct code to execute more quickly.

Ternary Operator

The ternary operator provides a shortcut for if conditions. The syntax is as follows:

Syntax

var varName = (condition) ? valueIfTrue : valueIfFalse;

For example:

var evenOrOdd = (number % 2 === 0) ? "even" : "odd";

The code sample below shows how the ternary operator works:

Code Sample:

ConditionalsAndLoops/Demos/ternary.html
---- C O D E   O M I T T E D ----

<script>
  var num = parseInt(prompt("Enter a number.",""));
  
  //without ternary
  if (num % 2 === 0) {
    alert(num + " is even.");
  } else {
    alert(num + " is odd.");
  }
  
  //with ternary
  var term = num % 2 === 0 ? "even" : "odd";
  alert(num + " is " + term);
</script>
---- C O D E   O M I T T E D ----

Code Explanation

The first block shows a regular if-else statement.

The second block shows how to accomplish the same thing in a couple of lines of code with the ternary operator.

Truthy and Falsy

JavaScript has a boolean data type, which has only two possible values: true or false. In addition, every value and expression in JavaScript can be converted to true or false.

When a non-boolean literal value, variable, or expressions is used in a boolean context (e.g, an if condition or with the default operator), it is implicitly converted to a boolean. This process is called Type Coercion. For example, look at the following code, which uses the default operator:

var a = 1 || 2;

The value 1 is interpreted as true, so a will get 1. Non-boolean values that are treated as true when used in a boolean context are said to be truthy.

Now examine the following code:

var a = 0 || 2;

The value 0 is interpreted as false, so a will get 2. Non-boolean values that are treated as false when used in a boolean context are said to be falsy.

The only falsy values are:

  1. 0, but not "0", which is a string.
  2. "" - a zero-length string.
  3. null
  4. undefined
  5. NaN - a special number value that means "Not a Number". For example, NaN is the result of division by zero.

All other values are truthy.

Conditional Processing

Duration: 20 to 30 minutes.

In this exercise, you will practice using conditional processing.

  1. Open ConditionalsAndLoops/Exercises/conditionals.html for editing.
  2. Notice that there is an onclick event handler on the button that calls the greetUser() function. Create this function in the script block.
  3. The function should do the following:
    1. Ask (via a prompt) if the user is right- or left-handed.
    2. If the user enters a value other than "right" or "left", prompt again.
    3. Ask (via a prompt) for the user's last name.
    4. If the user leaves the last name blank, prompt again.
    5. If the user enters a number for the last name, alert that a last name can't be a number and prompt again.
    6. After collecting the user's dominant hand and last name:
      • If the dominant hand is valid, pop up an alert that greets the user appropriately (e.g., "Hello Lefty Smith!")
      • If the dominant hand is not valid, pop up an alert that reads something like "XYZ is not a valid value for dominant hand!"
  4. Test your solution in a browser.

Challenge

  1. Allow the user to enter the dominant hand in any case.
  2. If the user enters a last name that does not start with a capital letter, prompt to try again.

Solution:

ConditionalsAndLoops/Solutions/conditionals.html
---- C O D E   O M I T T E D ----
<script>
function greetUser() {
  var dominantHand, lastName;
  
  dominantHand = prompt("Are you left- or right-handed?", "") || "";
  if (dominantHand !== "right" && dominantHand !== "left") {
    dominantHand = prompt("Try again: right or left?", "") || "";
  }
  
  lastName = prompt("What's your last name?", "") || "";
  if (lastName.length === 0) {
    lastName = prompt("No last name? Please re-enter:", "") || "";
  } else if (! isNaN(lastName)) {
    lastName = prompt("Names aren't numbers. Re-enter:", "") || "";
  }
  
  switch (dominantHand) {
    case "right" :
      alert("Hello Righty " + lastName + "!");
      break;
    case "left" :
      alert("Hello Lefty " + lastName + "!");
      break;
    default :
      alert(dominantHand + " is not a valid value for dominant hand!");
  }
}
</script>
---- C O D E   O M I T T E D ----

Code Explanation

Challenge Solution:

ConditionalsAndLoops/Solutions/conditionals-challenge.html
---- C O D E   O M I T T E D ----
<script>
function greetUser() {
  var dominantHand, lastName;
  
  dominantHand = prompt("Are you left- or right-handed?", "") || "";
  dominantHand = dominantHand.toLowerCase();
  if (dominantHand !== "right" && dominantHand !== "left") {
    dominantHand = prompt("Try again: right or left?", "") || "";
  }
  
  lastName = prompt("What's your last name?", "") || "";
  var firstLetter = lastName.substring(0, 1);
  if (lastName.length === 0) {
    lastName = prompt("No last name? Please re-enter:", "") || "";
  } else if (! isNaN(lastName)) {
    lastName = prompt("Names aren't numbers. Re-enter:", "") || "";
  } else if (firstLetter === firstLetter.toLowerCase()) {
    lastName = prompt("Names begin with capital letters.  Re-enter:", "") || "";
  }
  
  switch (dominantHand) {
    case "right" :
      alert("Hello Righty " + lastName + "!");
      break;
    case "left" :
      alert("Hello Lefty " + lastName + "!");
      break;
    default :
      alert(dominantHand + " is not a valid value for dominant hand!");
  }
}
</script>
---- C O D E   O M I T T E D ----

Code Explanation

Loops

There are several types of loops in JavaScript:

  • while
  • do...while
  • for
  • for...in
  • for...of

while Loop Syntax

Syntax

while (conditions) {
	statements;
}

The while loop first checks one or more conditions and then executes the statements in its body as long as those conditions are true. Something, usually a statement within the while block, must cause the condition to change so that it eventually becomes false and causes the loop to end. Otherwise, you get stuck in an infinite loop, which can bring down the browser. For example:

var i=0;
while (i < 5) {
	console.log(i);
	i++; // changing value of i
}

And here's the above code executed at Chrome DevTools Console:while Loop

do...while Loop Syntax

Syntax

do {
	statements;
} while (conditions);

The do...while loop checks the conditions after each execution of the statements in the body. Again, something, usually a statement within the do block, must cause the condition to change so that it eventually becomes false and causes the loop to end. For example:

var i=0;
do {
    console.log(i);
    i++; // changing value of i
} while (i < 5);

And here's the above code executed at Chrome DevTools Console:do...while Loop

Unlike with while loops, the statements in do...while loops will always execute at least one time because the conditions are not checked until the end of each iteration. The code below illustrates this:do...while vs. while Loop

for Loop Syntax

Syntax

for (initialization; conditions; change) {
	statements;
}

In for loops, the initialization, conditions, and change are all placed up front and separated by semi-colons. This makes it easy to remember to include a change statement that will eventually cause the loop to end.

for loops are often used to iterate through arrays. The length property of an array can be used to check how many elements the array contains. For example:

var fruit = ['Apples','Oranges','Bananas','Pears'];
for (var i=0; i<fruit.length; i++) {
    console.log(fruit[i]);
}

And here's the above code executed at Chrome DevTools Console:Looping through an Array

for...of Loop Syntax

Syntax

for (value of iterable) {
	statement;
}

for...of loops are used to loop through any iterable object - usually arrays, but there are other types of iterable objects as well. For example:

var fruit = ['Apples','Oranges','Bananas','Pears'];
for (var i of fruit) {
    console.log(i);
}

And here's the above code executed at Chrome DevTools Console:Looping through an Array with for...of

for...in Loop Syntax

Syntax

for (var item in object) {
	statements;
}

for...in loops are used to loop through object properties. A common mistake is to use this type of loop to iterate through arrays. Most of the time, this will work fine, but for reasons that are beyond the scope of this course, you should avoid using for...in loops to iterate through arrays. We cover the syntax here only because you are likely to see this type of loop used incorrectly and we want you to be able to recognize it. If you would like to learn more why it should be avoided, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration#Arrays.

break and continue

The break statement is used to break out of a loop, usually when some condition is met.

Syntax

for (var item of object) {
	doSomething(item);
	if (conditions) {
		break;
		// loop will stop executing
		// and afterLoop() will run
	}
}
afterLoop();

The following code illustrates how break works:Loop break Notice that the Bananas and Pears do not get logged, because the loop is broken as soon as Oranges, which contains "an" is found.

The continue statement is used to move on to the next iteration of the loop. It is used when a condition is met that makes it unnecessary to run the rest of the code in the loop body for that iteration.

Syntax

for (var item of object) {
	doSomething(item);
	if (conditions) {
		continue;
		// loop will move on to next item
		// doSomethingElse() won't be executed for this item
	}
	doSomethingElse(item);
}

The following code illustrates how continue works:Loop continue Notice that the Oranges and Bananas do not get logged, because both contain "an", and when that condition is met, the loop moves on to the next iteration.

Working with Loops

Duration: 20 to 30 minutes.

In this exercise, you will practice working with loops.

  1. Open ConditionalsAndLoops/Exercises/loops.html for editing. You will see that this file is similar to the solution to the challenge from the last exercise.
  2. Declare an additional variable called greeting.
  3. Create an array called presidents that contains the last names of four or more past presidents.
  4. Currently, the user only gets two tries to enter a valid dominantHand and lastName. Modify the code so that, in both cases, the user continues to get prompted until the data is valid.
    1. For dominantHand, the first prompt should be "Are you left- or right-handed?" Each subsequent prompt should be "Try again: right or left?"
    2. For lastName, it should just continue prompting "What's your last name?" until the user enters a valid last name.
  5. Change the switch block so that it assigns an appropriate value (e.g., "Hello Lefty Smith") to the greeting variable rather than popping up an alert.
  6. After the switch block, write code that alerts the user by name if he has the same last name as a president. There is no need to alert those people who have non-presidential names.

Challenge

  1. For those people who do not have presidential names, pop up an alert that tells them their names are not presidential.

Solution:

ConditionalsAndLoops/Solutions/loops.html
---- C O D E   O M I T T E D ----
<script>
function greetUser() {
  var dominantHand, lastName, greeting;
  var presidents = ["Washington", "Jefferson", "Lincoln", "Kennedy"];
  
  dominantHand = prompt("Are you left- or right-handed?", "") || "";
  dominantHand = dominantHand.toLowerCase();
  while (dominantHand !== "right" && dominantHand !== "left") {
    dominantHand = prompt("Try again: right or left?", "") || "";
  }
  
  do {
    lastName = prompt("What's your last name?", "") || "";
    var firstLetter = lastName.substring(0, 1);
  } while (lastName.length === 0
      || ! isNaN(lastName)
      || firstLetter === firstLetter.toLowerCase())
  
  switch (dominantHand) {
    case "right" :
      greeting = "Hello Righty " + lastName + "!";
      break;
    default : // If not right, must be left
      greeting = "Hello Lefty " + lastName + "!";
  }

  for (lName of presidents) {
    if (lName === lastName) {
      alert(greeting + ' Your name is presidential!');
      break; // No need to keep looking after we've found a match
    }
  }
}
</script>
---- C O D E   O M I T T E D ----

Code Explanation

Challenge Solution:

ConditionalsAndLoops/Solutions/loops-challenge.html
---- C O D E   O M I T T E D ----
  var match = false;
  for (lName of presidents) {
    if (lName === lastName) {
      alert(greeting + ' Your name is presidential!');
      match = true;
      break; // No need to keep looking after we've found a match
    }
  }
  if (!match) {
    alert(greeting + ' Your name is not presidential!');
  }
---- C O D E   O M I T T E D ----

Code Explanation

Array: forEach()

Another way to loop through arrays is to use the array's built-in forEach() method.

Syntax

myArray.forEach( function(item) {
	doSomething(item);
});

Each item of the array is passed to the function one by one. For example:

var fruit = ['Apples','Oranges','Bananas','Pears'];
fruit.forEach(function(item) {
    console.log(item);
});

And here's the above code executed at Chrome DevTools Console:Array forEach() Method