Conditions
Problem
The shipping that should not be there
An online shop promises free shipping on orders of €50 and up. Under €50, shipping is €4.99. The order is €62, and the program still adds shipping:
const total = 62;const shipping = 4.99;console.log(`To pay: €${total + shipping}`);To pay: €66.99The program runs every line, one after another. Here it has to choose: one line in one case, another line in another.
The idea
A comparison answers yes or no
First the program has to ask: is the total €50 or more? For this there are comparison operators. Their answer is not a number, but true or false: a value of type boolean.
const total = 62;console.log(total >= 50);console.log(total === 50);console.log(total !== 50);truefalsetrue| You write | It asks |
|---|---|
a > b, a < b |
greater, less |
a >= b, a <= b |
greater or equal, less or equal |
a === b |
are they equal |
a !== b |
are they different |
Be careful: === compares, and = stores a value. total === 50 asks whether the total is 50, and total = 50 makes it 50.
JavaScript also has == with two signs. It first turns both values into one type and only then compares, so the text "5" turns out to be equal to the number 5:
console.log("5" == 5);console.log("5" === 5);truefalseAlways write === and !==. That is also how you will see them in other people's code.
Text in JavaScript is compared with the same ===:
const answer = "yes";const yes = answer === "yes";console.log(yes);trueMore precisely, if you are curious
Decimal numbers are rarely exactly equal. The computer stores 0.1 and 0.2 approximately, so their sum is not exactly 0.3:
console.log(0.1 + 0.2 === 0.3);console.log(0.1 + 0.2);false0.30000000000000004For decimal numbers, ask whether they are close enough: Math.abs(a - b) < 0.000001. Comparisons with > and < do not have this problem.
The idea
if and else: one of two paths
Now the program can choose. if checks the condition in the parentheses. If it is true, it runs the block after it. If it is not, it runs the block after else:
const total = 62;let shipping;if (total >= 50) { shipping = 0;} else { shipping = 4.99;}console.log(`Shipping: €${shipping}`);Shipping: €0For an order of €18.50 the same program prints Shipping: €4.99. Only one of the blocks runs, never both.
else is not required. Without it, if the condition is not true, the block is simply skipped and the program continues after it.
More precisely, if you are curious
- If the block is one line, the braces
{ }can be left out. Do not do it: as soon as you add a second line, it will be outside theif, and the indentation will fool you into thinking it is inside. - The condition can be any value, not only
trueorfalse. The number 0 and the empty text""count as false, everything else as true:
const total = 0;if (total) { console.log("There is a total");} else { console.log("0 counts as false");}0 counts as false- That is why
if (total = 50)is not an error: it stores 50 intotal, and 50 counts as true. The condition is true for any total, and the total is now something else:
let total = 10;if (total = 50) { console.log("Free shipping");}console.log(total);Free shipping50Try it
An order bigger than the stock
There are 3 items in the warehouse, and the customer orders 5.
What will the program print?
const stock = 3;let ordered = 5;if (ordered > stock) { console.log("Not enough in stock"); ordered = stock;}console.log(`Sending ${ordered} items`);5 > 3 is true, so the block runs: it prints the message and lowers the order to 3. The last line is after the block and always runs.
The idea
else if: more than two paths
A teacher turns test points into a grade. There are four possibilities. You put an if after the else:
const points = 76;if (points >= 90) { console.log("Excellent");} else if (points >= 75) { console.log("Very good");} else if (points >= 50) { console.log("Good");} else { console.log("Fail");}Very goodThe checks go from top to bottom. The first branch with a true condition runs, and the rest are skipped. 76 is not >= 90, but it is >= 75, so it is "Very good". The program never gets to >= 50, even though it is true too.
That is why the order matters: the strictest condition comes first. If points >= 50 were at the top, everyone with 50 points or more would get "Good".
const points = 76;if (points >= 90) { console.log("Excellent");} else if (points >= 75) { console.log("Very good");} else if (points >= 50) { console.log("Good");} else { console.log("Fail");}Step by step, in words
- points is 76.
- 76 >= 90? No. The "Excellent" branch is skipped.
- 76 >= 75? Yes. We go into the "Very good" branch.
- It prints "Very good".
- 76 >= 50 is true too, but it is not checked: the chain stops at the first true branch.
Try it
Find the bug
Everyone with 90 points or more gets "Excellent". A student with exactly 90 points gets "Very good". Which line is the bug on?
Pick the line with the bug.
points > 90 misses 90 itself. It has to be points >= 90. Bugs like this, "off by one", are common: when the condition is "from … and up", check what happens right at the boundary.
The idea
And, or, not
The cinema gives a discount ticket to children and to students. There are two conditions, and one is enough. You connect them with logical operators:
const age = 16;const student = false;if (age < 18 || student) { console.log("Discount ticket: €6");} else { console.log("Ticket: €10");}Discount ticket: €6a && bis true when both are true ("and").a || bis true when at least one is true ("or").!ais true whenais not true ("not"):!student.
Free shipping over €50 and only in the city is total >= 50 && inCity. A number is between 1 and 12 if month >= 1 && month <= 12. The math notation 1 <= month <= 12 does not work here, and it fails without an error: first 1 <= month becomes true or false, and then that is compared with 12 as 1 or 0. The result is always true, even for 13:
const month = 13;console.log(1 <= month <= 12);console.log(month >= 1 && month <= 12);truefalseMore precisely, if you are curious
- If the left operand already decides the answer, the right one is not checked: with
false && …and withtrue || …. This is called short-circuit evaluation, and sometimes it protects you from an error:count !== 0 && total / count > 10never divides by 0. &&comes before||, like*before+. When you mix them, add parentheses so it reads clearly:(a && b) || c.- A condition can also be inside another
if. That is a nestedif. This code is the same asif (total >= 50 && inCity):
if (total >= 50) { if (inCity) { shipping = 0; }}Try it
By 5 and by 7
What goes in the blank so the condition is true only for numbers divisible by both 5 and 7?
const number = 35;
if (number % 5 === 0 number % 7 === 0) {
console.log("Divisible by both 5 and 7");
}&&: both checks have to be true. With || one would be enough, and 10 would pass too.The idea
The ternary operator ? :
Sometimes the whole if is only there to pick one of two values. There is a short form for that, the ternary operator (it has three parts):
const points = 76;const message = points >= 50 ? "You passed!" : "You did not pass.";console.log(message);You passed!You read it like this: condition ? the value if it is true : the value if it is not. The same with if and else takes several lines, and here it is one.
Use it to pick a value. If the program has to do different things in the two cases, write if.
More precisely, if you are curious
- The two values can be of different types: text in one case and a number in the other. The program runs, but afterward you do not know what the variable holds. Pick between values of one type.
const points = 40;const result = points >= 50 ? "Passed" : 0;console.log(result);0- Ternary operators can be nested inside each other, but code like that is hard to read. For three or more possibilities, write
else if.
The idea
switch: choosing by value
The shop is open from 9:00 to 18:00 on weekdays, until 14:00 on Saturday, and it is closed on Sunday. If the day is a number (1 is Monday, 7 is Sunday), you compare it with several exact values. For this there is switch:
const day = 6;switch (day) { case 6: console.log("10:00–14:00"); break; case 7: console.log("Closed"); break; default: console.log("9:00–18:00");}10:00–14:00switchtakes the value in the parentheses and jumps to thecasewith the same value.breakends theswitch. Without it execution continues into the nextcase.defaultis for all other values, like the lastelse.- Several values with the same action are written one under the other:
case 6:and right after itcase 7:.
switch works with numbers and text. It compares like ===, so the text "6" does not match case 6. For checks like "from 50 and up", write if.
More precisely, if you are curious
- If you forget
break, execution "falls through" into the nextcase, with no check. For day 6, two lines are printed:
const day = 6;switch (day) { case 6: console.log("10:00–14:00"); case 7: console.log("Closed"); break; default: console.log("9:00–18:00");}10:00–14:00Closed- Because of
===, text from the input does not match a number in acase. Convert it first withNumber(...):
const day = "6";switch (day) { case 6: console.log("10:00–14:00"); break; default: console.log("No such day");}No such day- In Java and C#,
switchcan also give a value. In JavaScript it cannot: store the value in a variable in eachcase, or pick it with the ternary operator.
Exercise
Programs that choose
Solve the tasks in your editor. Each number in the input is on a separate line. Try each solution with input that goes through the other branches too.
1. A cinema ticket. Read the age. Up to 6 years old you get in free, up to 17 the ticket is €6, up to 64 it is €10, from 65 up it is €5. A negative age is an error.
15The ticket is €62. A mini calculator. Read a number, an operation (+, -, * or /) and a second number. Pick the action with switch on the text of the operation. You cannot divide by 0.
12/5Result: 2.43. A quadratic equation. Read a, b and c from ax² + bx + c = 0. The discriminant is D = b² − 4ac. If D is positive, there are two roots: (−b ± √D) / 2a. If D is 0, there is one root: −b / 2a. If D is negative, there are no real roots. If a = 0, the equation is not quadratic.
1-32x1 = 2.00, x2 = 1.004. A valid date. Read a day, a month and a year and say whether the date exists. Find the number of days in the month with switch. February has 29 days in a leap year: divisible by 4 but not by 100, or divisible by 400.
2922023Invalid dateFor 29, 2, 2024 the output is Valid date.
More tasks
- Even or odd. For 7:
Odd. - Positive, negative or zero. For −5:
Negative. - Greater than 10. For 15:
Greater than 10. - Are they equal. Read two numbers. For 5 and 5:
Equal. - The bigger of two. Read two numbers and print the bigger one. Do it once with
ifand once with? :. - Absolute value. Without
Math.abs: if the number is negative, change its sign. - Yes or no. Read text. Print
truefor "yes",falsefor "no", andAnswer not understoodfor anything else. - By 5 and by 7. Say whether the number is divisible by both 5 and 7. For 35: yes, for 10: no.
- Three numbers in ascending order. Read three numbers and print them from the smallest to the biggest. For 7, 2, 5:
2 5 7. - The smallest and the biggest of five. Read five numbers into five variables. Remember the first one as both the smallest and the biggest, then compare each next one with it.
- Day of the week. Read a number from 1 to 7 and print the day:
1isMonday. For another number:No such day. Try it withswitch. - Age group. Up to 12 years old is a child, up to 19 a teenager, otherwise an adult.
- Season by month. December, January and February are winter, March to May is spring, and so on. For 4:
Spring. With switch, put several cases one under the other. - Is it a triangle. Three sides make a triangle if the sum of any two is bigger than the third. For 3, 4, 5: yes, for 1, 2, 3: no.
- A grade in words. Read a grade from 2 to 6 and print
Fail,Average,Good,Very goodorExcellent. - Guess the animal. The program asks questions with a "yes" or "no" answer and guesses which animal you thought of. Start with a greeting and a short explanation of the game. You can ask all the questions and then decide with
else if, or ask only what you need with nestedifstatements. The questions:
| Question | If "yes" | If "no" |
|---|---|---|
| Does it fly? | a bird or an insect | go on |
| Does it have feathers? | a bird | if it flies, an insect |
| Does it swim? | if it does not fly: a fish or a small water mammal | go on |
| Does it meow? | a cat | not a cat |
| Does it have fur? | a dog, a cat or another mammal | a lizard or another reptile |
| Is it green? | if it does not fly and does not swim: a frog or a lizard | go on |
| Does it roar? | a cow or a lion | go on |
| Does it have a trunk? | an elephant | go on |
An example (the input is the answer to each question, in order):
nononoyesyesnononoThink of an animal. I will ask you 8 questions. Answer yes or no.Does it fly?Does it have feathers?Does it swim?Does it meow?Does it have fur?Is it green?Does it roar?Does it have a trunk?I think it is a cat.Test