Courses Learn Blog Contact
Get Started →
Lesson 2

Day 2: Decisions and Functions

Branching, truthy and falsy, functions, arrow syntax and scope, ending in a result analyser built from real school rules.

Webbo3 Level 2: JavaScript Development 29 min read Free

Webbo3 Level 2 · JavaScript Development · Day 2 of 20

Decisions and Functions

Teaching your code to choose, and packaging that choice into something you can use again without copying it.

By the end of today you can

  • Ask your code yes-or-no questions with comparison and logical operators
  • Make decisions with if, else if and else, in the right order
  • Explain truthy and falsy values, and avoid the empty-field trap
  • Use switch when one value has many exact options
  • Write functions that take input and return a result
  • Use parameters, arguments and default values correctly
  • Explain scope, and why a variable sometimes "disappears"

Yesterday your code ran straight down the page and did the same thing every time. It stored values, calculated with them and printed the result.

That is a calculator. It is not yet an application.

An application looks at what it has been given and decides what to do about it. Did the student pass? Is the password correct? Is there enough money in the wallet? Every one of those is a question with only two possible answers: yes or no.

Today you will teach JavaScript to ask those questions, to act on the answers, and then to package that logic into functions, so you write it once and use it as many times as you like.

1. Conditions: Asking Yes-or-No Questions

Definition

A condition is a question your code asks that can only be answered with true or false.

You met the answer type yesterday: a boolean. A condition is simply any expression that produces a boolean.

Real-Life Example

Picture the admissions officer at a school. For every applicant she asks two questions: "Did this person score 50 or more?" and "Has this person paid the fee?"

She does not answer "maybe". Each answer is yes or no. Then she combines them: only a person with yes AND yes is admitted.

Your code does exactly this. It asks yes-or-no questions using comparison operators, and combines the answers using logical operators.

Types of Operators for Conditions

  1. Comparison operators: compare two values and give back true or false.
  2. Logical operators: combine or flip true and false answers.
OperatorMeaningKind
===Equal (value and type)Comparison
!==Not equalComparison
>Greater thanComparison
<Less thanComparison
>=Greater than or equal toComparison
<=Less than or equal toComparison
&&AND: both must be trueLogical
||OR: at least one must be trueLogical
!NOT: flips true to false, and false to trueLogical

Type 1: Comparison Operators

A comparison operator looks at two values and answers one question about them. Stop here for a second. Before you read the output, predict each line.

What this code doesWe want to see how each comparison operator answers one question about a value. So we store a single score and ask five different questions about it.
app.js
1
2
3
4
5
6
7
8
9
// Store the student's score
const score = 72;

// Ask five questions about the score
console.log(score > 50);   // is it greater than 50?
console.log(score < 50);   // is it less than 50?
console.log(score >= 72);  // is it 72 or more?
console.log(score === 72); // is it exactly 72?
console.log(score !== 72); // is it anything other than 72?
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
false
true
true
false

Notice score >= 72 is true. "Greater than or equal to" includes the number itself. That small difference between > and >= decides whether a student who scored exactly the pass mark passes, so choose it on purpose.

Type 2: AND (&&)

&& gives back true only when both sides are true. One false answer is enough to make the whole thing false.

What this code doesBefore using && on real data, we want to see every possible combination of true and false, so the rule "both must be true" is clear.
app.js
1
2
3
4
5
// && is true only when BOTH sides are true
console.log(true && true);   // both true
console.log(true && false);  // right side false
console.log(false && true);  // left side false
console.log(false && false); // both false
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
false
false
false

Now with real questions. A student needs 50 or more and a paid fee:

What this code doesNow the admission rule for real: a student is admitted only with a passing score AND a paid fee. We check both facts together.
app.js
1
2
3
4
5
6
// The two facts we know about this applicant
const score = 78;
const feePaid = false;

// Admitted only if the score passes AND the fee is paid
console.log(score >= 50 && feePaid);
OUTPUT   TERMINAL
➜ webbo3 node app.js
false

The score is fine, but the fee is not paid, so the answer is false.

Type 3: OR (||)

|| gives back true when at least one side is true. It is only false when both sides are false.

What this code doesWe want to see every combination for ||, so the rule "at least one must be true" is clear before we use it.
app.js
1
2
3
4
// || is true when AT LEAST ONE side is true
console.log(true || false);  // left side true
console.log(false || true);  // right side true
console.log(false || false); // neither is true
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
true
false

A bus company gives a discount to students or anyone aged 60 and above:

What this code doesA bus company gives a discount to students OR to anyone aged 60 and above. We check whether this passenger qualifies.
app.js
1
2
3
4
5
6
// The two facts we know about this passenger
const isStudent = false;
const age = 64;

// Discount if they are a student OR aged 60 and above
console.log(isStudent || age >= 60);
OUTPUT   TERMINAL
➜ webbo3 node app.js
true

This passenger is not a student, but is over 60, so they still get the discount.

Type 4: NOT (!)

! flips an answer. True becomes false, and false becomes true.

What this code doesWe want to see ! flip an answer: first on a real fact about a user, then on a plain true.
app.js
1
2
3
4
5
6
7
8
// The user has not logged in
const isLoggedIn = false;

// ! flips the answer: read it as "not logged in"
console.log(!isLoggedIn);

// Flipping true gives the opposite
console.log(!true);
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
false

Read !isLoggedIn out loud as "not logged in". Because the user is not logged in, "not logged in" is true.

Name Your Conditions

You can write a long condition on one line, but it quickly becomes hard to read. Give each question a name instead.

What this code doesWe want to check eligibility in a way anyone can read. So we give each question a name first, then combine the named answers.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
// The raw facts
const score = 78;
const attendance = 0.6;

// Give each question a name that says what it means
const passedTest = score >= 50;
const attendedEnough = attendance >= 0.75;

// Print each answer, then combine them
console.log('Passed test:', passedTest);
console.log('Attended enough:', attendedEnough);
console.log('Eligible:', passedTest && attendedEnough);
OUTPUT   TERMINAL
➜ webbo3 node app.js
Passed test: true
Attended enough: false
Eligible: false
Important Rule

passedTest && attendedEnough says what it means. score >= 50 && attendance >= 0.75 makes the reader work it out. Naming a condition costs one line and saves every future reader, including you next month.

Overall Example

A scholarship goes to students with an average of 70 or more who attended at least 75% of classes, or to anyone who won the national quiz.

What this code doesWe want to decide a scholarship using a rule that has both AND and OR in it, grouping the parts with brackets so the order is clear.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// The facts about this student
const average = 74;
const attendance = 0.8;
const wonNationalQuiz = false;

// Name each part of the scholarship rule
const strongResult = average >= 70;
const goodAttendance = attendance >= 0.75;

// Both good results AND attendance, OR a national quiz win
const getsScholarship = (strongResult && goodAttendance) || wonNationalQuiz;

// Show the final decision
console.log('Scholarship:', getsScholarship);
OUTPUT   TERMINAL
➜ webbo3 node app.js
Scholarship: true

Both parts of the first group are true, so the brackets give true. true || false is true, so this student gets the scholarship.

Try This

A cinema lets you in if you are 18 or older and you have a ticket. Write two named conditions and print whether this person can enter.

What this code doesWe want to decide whether a person can enter a cinema: they must be old enough AND have a ticket.
app.js
1
2
3
4
5
6
7
8
9
// The facts about this person
const age = 17;
const hasTicket = true;

// Name the age question
const oldEnough = age >= 18;

// They can enter only if they are old enough AND have a ticket
console.log('Can enter:', oldEnough && hasTicket);
OUTPUT   TERMINAL
➜ webbo3 node app.js
Can enter: false

Now change age to 21 and predict the new output before you run it.

Picture This

Picture a checklist on a clipboard. Each line is a question with a tick or a cross. AND needs every line ticked. OR needs just one tick. NOT swaps a tick for a cross. Every condition you write is that clipboard.

2. if, else if and else: Acting on the Answer

Definition

An if statement runs a block of code only when its condition is true. else if and else give your code other paths to take when it is false.

Real-Life Example

At a traffic light, a driver makes the same decision every time: if the light is green, go. Otherwise, if it is amber, get ready to stop. Otherwise, stop.

Only one of those actions happens, and the driver checks them in order. That is exactly how if, else if and else work.

Types of if Statements

  1. if: do something only when the condition is true.
  2. if...else: choose between two paths.
  3. if...else if...else: choose between many paths.

Type 1: if

The shape is always the same: a condition in round brackets, and a block in curly braces that runs only when the condition is true.

What this code doesWe want the purchase message to appear only when the wallet has enough money, and we add a final line to show what always runs.
app.js
1
2
3
4
5
6
7
8
9
10
11
// How much money is in the wallet, and what the item costs
const walletBalance = 5000;
const price = 1500;

// Only runs when there is enough money
if (walletBalance >= price) {
  console.log('Purchase successful');
}

// This line always runs, after the if
console.log('Done');
OUTPUT   TERMINAL
➜ webbo3 node app.js
Purchase successful
Done

When the condition is false, the block is simply skipped. Change price to 8000 and only Done is printed.

Type 2: if...else

else is the path taken when the condition is false. Exactly one of the two blocks runs.

What this code doesWe want to give one of two responses to a PIN: welcome the user when it is right, and warn them when it is wrong.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
// The PIN the user typed, and the real PIN
const enteredPin = '1234';
const correctPin = '4321';

// Compare them: exactly one of the two blocks will run
if (enteredPin === correctPin) {
  // Runs when the PINs match
  console.log('Welcome back');
} else {
  // Runs when they do not
  console.log('Wrong PIN, try again');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Wrong PIN, try again

Type 3: if...else if...else

When there are more than two outcomes, add else if branches. JavaScript checks them from top to bottom and runs the first one that is true. else catches everything that matched nothing.

What this code doesWe want to turn a score into a grade from several possible grades, checking the highest grade first.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// The score to grade
const score = 64;

// Checked from top to bottom; the first true branch wins
if (score >= 70) {
  console.log('A');
} else if (score >= 60) {
  console.log('B');
} else if (score >= 50) {
  console.log('C');
} else {
  // Runs only when nothing above matched
  console.log('Fail');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
B

64 is not 70 or more, so the first branch is skipped. It is 60 or more, so the second branch runs, and JavaScript stops looking.

Common Mistake: The Order of Your Branches

Because the first true branch wins, the order is not cosmetic. Predict what this prints for a score of 95:

What this code doesWe want to see what goes wrong when the conditions are in the wrong order, with the broadest one checked first.
app.js
1
2
3
4
5
6
7
8
9
10
11
// A very high score
const score = 95;

// The broadest condition is checked FIRST here
if (score >= 50) {
  console.log('C');
} else if (score >= 60) {
  console.log('B');
} else if (score >= 70) {
  console.log('A');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
C
Why This Happens

95 is greater than 50, and that branch is checked first, so it wins. The other branches are never looked at. When every grade comes out the same, check the order before anything else: the strictest condition goes first, the broadest one last.

Overall Example

A phone shows a different message depending on how much data you have left. This uses a condition from section 1 inside an if chain:

What this code doesWe want a phone to show the right data message for three situations, using a condition from section 1 inside the chain.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// How much data is left, and whether the bundle renews itself
const dataLeftMB = 300;
const autoRenew = false;

// Out of data completely?
if (dataLeftMB === 0) {
  console.log('You are out of data');
// Low on data AND not set to renew?
} else if (dataLeftMB < 500 && !autoRenew) {
  console.log('Running low: buy a bundle soon');
// Everything else
} else {
  console.log('You have enough data');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Running low: buy a bundle soon

300 is not 0, so the first branch is skipped. 300 is less than 500 and auto-renew is off, so the second branch runs.

Try This

Write an if chain that gives weather advice: 30 or more prints "Stay hydrated", 20 or more prints "Nice weather", anything else prints "Take a jacket".

What this code doesWe want to give weather advice for three temperature ranges, checking the hottest range first.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
// Today's temperature in degrees Celsius
const temperature = 24;

// Hottest case first
if (temperature >= 30) {
  console.log('Stay hydrated');
// Warm, but not hot
} else if (temperature >= 20) {
  console.log('Nice weather');
// Anything cooler
} else {
  console.log('Take a jacket');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Nice weather

Test it with 35 and with 12, and predict each output first.

Picture This

Picture a road with several turnings, each with a signpost. You drive past them in order and take the first turning whose sign matches you. Once you have turned, you never see the other signs. else is the road straight ahead for anyone who matched nothing.

3. Truthy and Falsy: What Counts as Yes

Definition

An if expects true or false, but JavaScript lets you put any value there. When it does, JavaScript converts the value to a boolean.

Values that become false are called falsy. Every other value is truthy.

Real-Life Example

A teacher asks: "Did you bring anything to hand in?" An empty hand counts as no. A hand holding anything at all counts as yes, even a sheet of paper that says "nothing".

JavaScript judges values the same way. A few "empty" values count as no. Everything else, including some things that look empty, counts as yes.

Types: Falsy and Truthy Values

To see how JavaScript judges a value, pass it to Boolean(). It shows you exactly what an if would decide.

Falsy valueWhat it is
falseThe boolean false itself
0The number zero
''An empty string (text with nothing in it)
nullDeliberately empty
undefinedNo value assigned yet
NaN"Not a Number", the result of a failed number conversion

These six are the falsy values you will actually meet. Everything else is truthy.

Type 1: Falsy Values

What this code doesWe want to see how JavaScript judges each of the six falsy values, so we pass each one to Boolean().
app.js
1
2
3
4
5
6
7
// Boolean() shows how an if would judge each value
console.log(Boolean(false));     // the boolean false
console.log(Boolean(0));         // the number zero
console.log(Boolean(''));        // an empty string
console.log(Boolean(null));      // deliberately empty
console.log(Boolean(undefined)); // never given a value
console.log(Boolean(NaN));       // a failed number conversion
OUTPUT   TERMINAL
➜ webbo3 node app.js
false
false
false
false
false
false

Type 2: Truthy Values

Predict these before reading the output. Some of them surprise everyone.

What this code doesWe want to check values that look empty or look false, to see how JavaScript really judges them.
app.js
1
2
3
4
5
6
// Values that are not on the falsy list
console.log(Boolean('hello')); // text with letters
console.log(Boolean(42));      // a number that is not zero
console.log(Boolean('0'));     // the TEXT "0", not the number
console.log(Boolean('false')); // the TEXT "false"
console.log(Boolean([]));      // an empty array
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
true
true
true
true

'0' and 'false' are strings with characters in them, so they are not empty. [] is an empty array, but the array itself still exists, so it is truthy.

Using It in an if

What this code doesWe want to greet a user by name, and fall back to a general greeting when they typed no name at all.
app.js
1
2
3
4
5
6
7
8
9
10
// The user left the name box empty
const username = '';

// An empty string counts as false in an if
if (username) {
  console.log(`Hello, ${username}`);
} else {
  // Fallback when no name was typed
  console.log('Hello, guest');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Hello, guest

The empty string is falsy, so the else branch runs. This is a very common way to check "did the user type anything?"

Common Mistake: The Empty-Field Trap

Remember from Day 1: values from a form arrive as strings, and you convert them with Number(). Now watch what happens when a user genuinely types 0:

What this code doesWe want to reject an order when the quantity box is empty. Watch what this does when the user genuinely types 0.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
// What the user typed into the quantity box
const typedQuantity = '0';

// Convert the text into a number
const quantity = Number(typedQuantity);

// Reject the order when quantity is falsy
if (!quantity) {
  console.log('Please enter a quantity');
} else {
  console.log(`Ordering ${quantity}`);
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Please enter a quantity
Why This Is a Bug

The user did type something. But 0 is falsy, so !quantity is true and their valid answer is rejected as if the box were empty.

When "empty" and "zero" must mean different things, test for exactly what you mean:

What this code doesWe want to fix the empty-field trap: test for an empty box directly, so a typed 0 is accepted.
app.js
1
2
3
4
5
6
7
8
9
10
// What the user typed into the quantity box
const typedQuantity = '0';

// Test for exactly what "empty" means: no text at all
if (typedQuantity === '') {
  console.log('Please enter a quantity');
} else {
  // Something was typed, so convert and use it
  console.log(`Ordering ${Number(typedQuantity)}`);
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Ordering 0

Overall Example

Show a display name, falling back to a default when the profile has none:

What this code doesWe want to show the best available name: the nickname if there is one, the first name if not, and a general word otherwise.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// This profile has no nickname, but it has a first name
const nickname = null;
const firstName = 'Aisha';

// Use the nickname if there is one
if (nickname) {
  console.log(`Welcome, ${nickname}`);
// Otherwise use the first name
} else if (firstName) {
  console.log(`Welcome, ${firstName}`);
// Otherwise use a general greeting
} else {
  console.log('Welcome, student');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Welcome, Aisha
Try This

Predict whether each value is truthy or falsy, then check with Boolean():

What this code doesPractise predicting: three more values to judge as truthy or falsy.
app.js
1
2
3
4
// Predict each one before you run it
console.log(Boolean(' '));           // a single space
console.log(Boolean(-5));            // a negative number
console.log(Boolean(Number('abc'))); // converting letters to a number
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
true
false

A single space is a character, so the string is not empty. Number('abc') fails and gives NaN, which is falsy.

Picture This

Picture a bouncer who only turns away six specific people: false, zero, the empty string, null, undefined and NaN. Everyone else walks in, even someone wearing a T-shirt that says "false".

4. switch: One Value, Many Exact Options

Definition

switch compares one value against a list of exact options and runs the code for the option that matches.

It is not a new kind of logic. It is a tidier shape for one situation that an if chain can also handle.

Real-Life Example

Dial a USSD code on your phone and you get a menu: press 1 to check your balance, 2 to buy airtime, 3 to buy data. The phone takes the one number you pressed and jumps to the matching option. Anything else gets "Invalid option".

How It Works

PartWhat it does
switch (value)The one value being checked
case ...:One exact option to compare against
breakStops here, so the next case does not run
default:Runs when no case matched, like else

Example 1: A Basic switch

What this code doesWe want to run the menu action that matches the option the user pressed, like a USSD menu.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// The menu option the user pressed
const option = 2;

// Compare option against each case, one by one
switch (option) {
  case 1:
    console.log('Your balance is N2,500');
    break; // stop here
  case 2:
    console.log('Buy airtime');
    break; // stop here
  case 3:
    console.log('Buy data');
    break; // stop here
  default:
    // Runs when no case matched
    console.log('Invalid option');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Buy airtime

Example 2: Two Options, One Outcome

Put cases directly on top of each other when they share a result. Here, Saturday and Sunday both get the weekend rate:

What this code doesWe want Saturday and Sunday to share one price, without writing the same line twice.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// The day being priced
const day = 'sunday';

switch (day) {
  // Two cases stacked together share one result
  case 'saturday':
  case 'sunday':
    console.log('Weekend rate');
    break;
  case 'friday':
    console.log('Friday rate');
    break;
  default:
    // Every other day
    console.log('Weekday rate');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Weekend rate

Common Mistake: Forgetting break

Without break, JavaScript does not stop at the matching case. It carries on and runs every case below it too. Predict this output:

What this code doesWe want to see what happens when break is left out of a switch.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
// The menu option the user pressed
const option = 1;

// Notice: there is no break in any case below
switch (option) {
  case 1:
    console.log('Check balance');
  case 2:
    console.log('Buy airtime');
  case 3:
    console.log('Buy data');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Check balance
Buy airtime
Buy data
Why This Happens

Case 1 matched, and with no break the code "falls through" into cases 2 and 3. In Example 2 the fall-through was deliberate, with nothing between the two cases. Everywhere else, a missing break is a bug.

Watch Out: switch Uses ===

switch compares with strict equality, so the type must match too. A form gives you the string '1', not the number 1:

What this code doesWe want to see why text from a form does not match a number case in a switch.
app.js
1
2
3
4
5
6
7
8
9
10
11
// A form gives you text, not a number
const typed = '1';

// switch compares with ===, so the type must match too
switch (typed) {
  case 1: // this case is the NUMBER 1
    console.log('Check balance');
    break;
  default:
    console.log('Invalid option');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Invalid option

'1' === 1 is false, so nothing matches. Convert first with Number(typed), or write the cases as strings.

switch or if?

UseWhen
switchOne value compared against several exact options
if / else ifRanges (score >= 70), or conditions that check different things

Overall Example

The full USSD menu, with the typed option converted to a number first:

What this code doesWe want a complete USSD menu that works with what the phone actually sends, which is text, so we convert it first.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// The option arrives from the phone as text
const typedOption = '3';

// Convert it to a number so it can match the cases
const option = Number(typedOption);

// Jump to the matching menu item
switch (option) {
  case 1:
    console.log('Your balance is N2,500');
    break;
  case 2:
    console.log('Enter airtime amount');
    break;
  case 3:
    console.log('Choose a data bundle');
    break;
  default:
    // Any number that is not on the menu
    console.log('Invalid option, try again');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Choose a data bundle
Try This

Write a switch that turns a grade letter into a message: A prints "Excellent", B prints "Very good", C prints "Good", and anything else prints "Keep going".

What this code doesWe want to turn a grade letter into an encouraging message.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// The student's grade letter
const grade = 'B';

// One message per grade
switch (grade) {
  case 'A':
    console.log('Excellent');
    break;
  case 'B':
    console.log('Very good');
    break;
  case 'C':
    console.log('Good');
    break;
  default:
    // Any other grade
    console.log('Keep going');
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Very good
Picture This

Picture a lift. You press one button, and the lift goes to that exact floor. break is the lift stopping. Forget it and the lift keeps going past every floor below. default is the lift telling you "that floor does not exist".

5. Functions: Write It Once, Use It Everywhere

Definition

A function is a named, reusable block of code that does one job. You define it once, and you call it whenever you need that job done.

Real-Life Example

Think of a blender. You do not rebuild the blender every time you want a smoothie. You put ingredients in, press the button, and get a smoothie back.

A function is the blender. What you put in are its inputs. What comes out is its return value. And you can use it again tomorrow with different fruit.

Why You Need Functions

Without functions, the grading logic from section 2 would be copied for every single student. Change the pass mark and you would have to find and fix every copy. With a function, you fix it in one place.

The Parts of a Function

PartExampleMeaning
KeywordfunctionTells JavaScript you are defining a function
NamegradeForWhat you will call it by
Parameters(score)The inputs it expects
Body{ ... }The code that does the job
ReturnreturnThe value it hands back
CallgradeFor(64)Actually running it

Types of Function Syntax

  1. Function declaration: the classic form.
  2. Function expression: a function stored in a variable.
  3. Arrow function: a shorter way to write a function expression.

All three make a function. You will see all three in real code, so you need to read all three.

Type 1: Function Declaration

What this code doesWe want to write a welcome message once and be able to show it as many times as we like.
app.js
1
2
3
4
5
6
7
8
// Define the function: this prints nothing yet
function welcome() {
  console.log('Welcome to Webbo3');
}

// Call it twice: each call runs the body once
welcome();
welcome();
OUTPUT   TERMINAL
➜ webbo3 node app.js
Welcome to Webbo3
Welcome to Webbo3

Defining the function prints nothing. Each welcome() call runs the body once, which is why the line appears twice.

Most functions take input and give a value back with return:

What this code doesWe want one function that adds any two numbers and hands the answer back to us.
app.js
1
2
3
4
5
6
7
8
9
// Define a function that takes two numbers
function add(a, b) {
  // Hand the sum back to whoever called it
  return a + b;
}

// Call it with different arguments and print the results
console.log(add(2, 3));
console.log(add(10, 20));
OUTPUT   TERMINAL
➜ webbo3 node app.js
5
30

return Is Not the Same as console.log

console.log only shows a value on screen. return hands the value back to the code that called the function, so that code can keep using it.

What this code doesWe want to prove that a returned value can be stored and used again, which console.log alone can never do.
app.js
1
2
3
4
5
6
7
8
9
10
// A function that returns twice the number it is given
function double(n) {
  return n * 2;
}

// The returned value is stored in a variable
const result = double(5);

// ...and can be used in more calculations
console.log(result + 1);
OUTPUT   TERMINAL
➜ webbo3 node app.js
11

double(5) became the value 10, which was stored and then used in a calculation. A console.log inside the function could never have done that.

Type 2: Function Expression

Here the function has no name of its own. It is stored in a variable, and you call it through the variable name.

What this code doesWe want to write the same kind of function a second way: stored inside a variable.
app.js
1
2
3
4
5
6
7
// Store a function in a variable
const triple = function (n) {
  return n * 3;
};

// Call it through the variable's name
console.log(triple(4));
OUTPUT   TERMINAL
➜ webbo3 node app.js
12

Type 3: Arrow Function

An arrow function drops the word function and uses =>. When the body is a single expression with no braces, the value is returned automatically.

What this code doesWe want to write short functions with the arrow syntax, where a single expression is returned automatically.
app.js
1
2
3
4
5
6
7
// Arrow functions: no braces means the value is returned automatically
const square = (n) => n * n;
const area = (width, height) => width * height;

// Call them like any other function
console.log(square(6));
console.log(area(3, 5));
OUTPUT   TERMINAL
➜ webbo3 node app.js
36
15

Common Mistake: Forgetting return

A function with no return still runs, but it hands back undefined.

What this code doesWe want to see what a function gives back when we forget to write return.
app.js
1
2
3
4
5
6
7
8
// This function calculates a total...
function addVat(amount) {
  const total = amount * 1.075;
  // ...but never returns it
}

// So the call hands back nothing
console.log(addVat(1000));
OUTPUT   TERMINAL
➜ webbo3 node app.js
undefined

The same trap hides inside arrow functions. With braces, the automatic return is gone:

What this code doesWe want to compare two arrow functions that look almost the same, to see why the braces matter.
app.js
1
2
3
4
5
6
7
8
9
// With braces: the arrow needs an explicit return, and has none
const withBraces = (n) => { n * 2; };

// Without braces: the value is returned automatically
const withoutBraces = (n) => n * 2;

// Compare what each one gives back
console.log(withBraces(4));
console.log(withoutBraces(4));
OUTPUT   TERMINAL
➜ webbo3 node app.js
undefined
8
Why This Matters

undefined does not cause an error where the mistake is. It travels quietly through your program and breaks something far away. When a function gives you undefined, look for the missing return first.

Early Return

return leaves the function immediately. That lets you drop the else branches entirely, because once a line returns, nothing below it runs:

What this code doesWe want to grade scores with a function that leaves as soon as it knows the answer, so no else branches are needed.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
// Each return leaves the function immediately
function gradeFor(score) {
  if (score >= 70) return 'A'; // stop here for 70 and above
  if (score >= 60) return 'B'; // only reached below 70
  if (score >= 50) return 'C'; // only reached below 60
  return 'F';                  // everything else
}

// Grade three different scores
console.log(gradeFor(95));
console.log(gradeFor(64));
console.log(gradeFor(31));
OUTPUT   TERMINAL
➜ webbo3 node app.js
A
B
F

This pattern is called an early return. It keeps decision logic flat and easy to read.

Overall Example

Two small functions working together: one calculates, the other formats.

What this code doesWe want two small functions to work together: one does the maths, the other formats a receipt line.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Job 1: calculate the cost of one line
function lineTotal(price, quantity) {
  return price * quantity;
}

// Job 2: format that line for a receipt
function receiptLine(item, price, quantity) {
  // Reuse the first function to do the maths
  const total = lineTotal(price, quantity);
  return `${item} x${quantity}: N${total}`;
}

// Print two receipt lines
console.log(receiptLine('Data bundle', 1500, 3));
console.log(receiptLine('Airtime', 500, 2));
OUTPUT   TERMINAL
➜ webbo3 node app.js
Data bundle x3: N4500
Airtime x2: N1000

receiptLine calls lineTotal to do the maths. Each function does one job, and together they do something useful.

Try This

Write a function fullName that takes a first name and a last name and returns them joined with a space. Then print it for two people.

What this code doesPractise: a function that builds a full name from a first name and a last name.
app.js
1
2
3
4
5
6
7
8
// Join a first name and a last name with a space
function fullName(first, last) {
  return `${first} ${last}`;
}

// Try it for two people
console.log(fullName('Aisha', 'Bello'));
console.log(fullName('Tunde', 'Okafor'));
OUTPUT   TERMINAL
➜ webbo3 node app.js
Aisha Bello
Tunde Okafor

Now rewrite it as an arrow function and check that the output is identical.

Picture This

Picture a machine on a table with a slot on top and a tray at the bottom. You drop things in the slot (the arguments), the machine does its job (the body), and the result lands in the tray (the return value). No tray means you get nothing back: undefined.

6. Parameters, Arguments and Default Values

Definition

Parameters are the names listed in a function's definition. They are placeholders. Arguments are the actual values you pass in when you call the function.

Real-Life Example

A registration form says "Name: ______" and "Course: ______". The blank lines are the parameters. What you write on them, "Aisha" and "JavaScript", are the arguments.

Some forms even pre-fill a blank for you, like "Country: Nigeria", which you can change. That is a default value.

Types

  1. Parameters: the placeholders in the definition.
  2. Arguments: the real values passed in the call.
  3. Default parameters: a value used when no argument is passed.

Type 1 and 2: Parameters and Arguments

What this code doesWe want to see how the values in a call fill the placeholders in the function, in order.
app.js
1
2
3
4
5
6
7
8
// name and course are the PARAMETERS (the placeholders)
function enrol(name, course) {
  return `${name} is enrolled in ${course}`;
}

// The values in the calls are the ARGUMENTS, filled in order
console.log(enrol('Aisha', 'JavaScript'));
console.log(enrol('Musa', 'Data Analysis'));
OUTPUT   TERMINAL
➜ webbo3 node app.js
Aisha is enrolled in JavaScript
Musa is enrolled in Data Analysis

name and course are the parameters. 'Aisha' and 'JavaScript' are the arguments. Arguments fill parameters in order: the first argument goes into the first parameter.

What If You Pass Too Few Arguments?

A parameter with no argument becomes undefined. Predict this:

What this code doesWe want to see what happens when a function is called with fewer arguments than it expects.
app.js
1
2
3
4
5
6
7
// A function that expects two numbers
function add(a, b) {
  return a + b;
}

// Called with only ONE argument, so b gets nothing
console.log(add(5));
OUTPUT   TERMINAL
➜ webbo3 node app.js
NaN

b was undefined, and 5 + undefined is NaN. That is exactly the problem default values solve.

Type 3: Default Parameters

Write the default straight into the parameter list. It is used only when the caller does not pass that argument.

What this code doesWe want VAT to be 7.5% unless the caller says otherwise, including when the caller asks for 0%.
app.js
1
2
3
4
5
6
7
8
9
// vat falls back to 7.5 when the caller does not pass it
function totalWithVat(amount, vat = 7.5) {
  // Add the VAT percentage on top of the amount
  return amount + (amount * vat / 100);
}

console.log(totalWithVat(1000));     // no vat passed: the default is used
console.log(totalWithVat(1000, 10)); // vat of 10%
console.log(totalWithVat(1000, 0));  // vat of 0%, meaning no VAT
OUTPUT   TERMINAL
➜ webbo3 node app.js
1075
1100
1000

The last call matters. The caller passed 0, meaning "no VAT", and got exactly that.

Common Mistake: Using || for Defaults

You will see older code write defaults with ||. Look what it does to that same 0:

What this code doesWe want to see why the older || way of writing a default breaks when the caller passes 0.
app.js
1
2
3
4
5
6
7
8
9
// The older way of writing a default
function totalWithVat(amount, vat) {
  // Use 7.5 whenever vat is falsy
  vat = vat || 7.5;
  return amount + (amount * vat / 100);
}

// The caller asks for 0% VAT
console.log(totalWithVat(1000, 0));
OUTPUT   TERMINAL
➜ webbo3 node app.js
1075
Why This Happens

0 is falsy (section 3), so vat || 7.5 throws the 0 away and uses 7.5. A default parameter only fills in when the value is undefined, so a real 0 is kept. Use default parameters.

Overall Example

What this code doesWe want one function that covers the common case with defaults, and still lets the caller change any value.
app.js
1
2
3
4
5
6
7
8
9
10
// bundles defaults to 1, and discount defaults to 0
function bundleCost(pricePerBundle, bundles = 1, discount = 0) {
  // Multiply first, then take the discount off
  const total = pricePerBundle * bundles;
  return total - discount;
}

console.log(bundleCost(1500));         // both defaults used
console.log(bundleCost(1500, 3));      // three bundles, no discount
console.log(bundleCost(1500, 3, 500)); // three bundles, N500 off
OUTPUT   TERMINAL
➜ webbo3 node app.js
1500
4500
4000

One function, three ways to call it. The defaults cover the common case, and the caller can override any of them.

Try This

Write greet(name, greeting) where greeting defaults to "Hello". Call it once with one argument and once with two.

What this code doesPractise: a greeting that says "Hello" unless the caller chooses different words.
app.js
1
2
3
4
5
6
7
// greeting is pre-filled with 'Hello'
function greet(name, greeting = 'Hello') {
  return `${greeting}, ${name}!`;
}

console.log(greet('Chidi'));                 // uses the default
console.log(greet('Chidi', 'Good morning')); // overrides it
OUTPUT   TERMINAL
➜ webbo3 node app.js
Hello, Chidi!
Good morning, Chidi!
Picture This

Picture a form with labelled blanks. The labels are the parameters. What you write in the blanks are the arguments. A blank that comes pre-filled is a default value: it stays unless you write something else over it.

7. Scope: Why Your Variable "Disappeared"

Definition

Scope is the part of your code where a variable can be seen and used. Outside its scope, the variable simply does not exist.

Real-Life Example

Think about notices at a school. A notice on the main gate is seen by the whole school. A notice on a classroom board is seen only by that class. A note passed inside one group is seen only by that group.

Variables work the same way. Where you declare a variable decides who can see it.

Types of Scope

  1. Global scope: declared outside every function and block. Visible everywhere.
  2. Function scope: declared inside a function. Visible only inside that function.
  3. Block scope: declared with let or const inside curly braces, such as an if. Visible only inside those braces.

Type 1: Global Scope

What this code doesWe want to see that a variable declared outside everything can be used both inside a function and outside it.
app.js
1
2
3
4
5
6
7
8
9
10
11
// Declared outside everything: GLOBAL scope
const schoolName = 'Webbo3 Academy';

// A function can read a global variable
function showSchool() {
  console.log(schoolName);
}

// Use it from inside the function, then from outside
showSchool();
console.log(schoolName);
OUTPUT   TERMINAL
➜ webbo3 node app.js
Webbo3 Academy
Webbo3 Academy

The variable lives outside the function, so both the function and the rest of the code can read it.

Type 2: Function Scope

What this code doesWe want to see where a variable declared inside a function can be used, and where it cannot.
app.js
1
2
3
4
5
6
7
8
9
10
11
function makeGreeting() {
  // Declared inside the function: FUNCTION scope
  const greeting = 'Hello from inside';
  console.log(greeting);
}

// Works: the function uses its own variable
makeGreeting();

// Outside the function, greeting does not exist
console.log(greeting);
OUTPUT   TERMINAL
➜ webbo3 node app.js
Hello from inside
ReferenceError: greeting is not defined

Inside the function, greeting works. Outside it, JavaScript has never heard of it, so the program stops with an error.

Type 3: Block Scope

What this code doesWe want to see that a variable declared inside an if block exists only within its braces.
app.js
1
2
3
4
5
6
7
8
if (true) {
  // Declared inside the braces: BLOCK scope
  const inside = 'only here';
  console.log(inside);
}

// Outside the braces, inside does not exist
console.log(inside);
OUTPUT   TERMINAL
➜ webbo3 node app.js
only here
ReferenceError: inside is not defined

The curly braces of the if are a boundary. inside exists within them and nowhere else.

Common Mistake: Declaring Inside, Using Outside

This is the most common reason a variable "disappears". The fix is to declare it one level up, before the block, with let, and only assign it inside:

What this code doesWe want to keep a result that is set inside an if, by declaring it before the block.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// The score to check
const score = 64;

// Declare result OUTSIDE the if, with no value yet
let result;

// Only assign it inside the branches
if (score >= 50) {
  result = 'Pass';
} else {
  result = 'Fail';
}

// It still exists here, after the if
console.log(result);
OUTPUT   TERMINAL
➜ webbo3 node app.js
Pass
When You See This Error

ReferenceError: ... is not defined almost always means the same thing: you declared the variable inside a block or function and tried to use it outside. Move the declaration up one level.

Overall Example

What this code doesWe want to see all three scopes working together in one realistic function.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Global: every function can read the pass mark
const passMark = 50;

function checkResult(name, score) {
  // Function scope: exists anywhere inside checkResult
  const message = `${name} scored ${score}`;

  if (score >= passMark) {
    // Block scope: exists only inside this if
    const note = 'well done';
    return `${message}: Pass, ${note}`;
  }

  // note is not available here, but message is
  return `${message}: Fail`;
}

// Check two students
console.log(checkResult('Amaka', 72));
console.log(checkResult('Femi', 41));
OUTPUT   TERMINAL
➜ webbo3 node app.js
Amaka scored 72: Pass, well done
Femi scored 41: Fail

passMark is global, so the function can read it. message belongs to the function. note belongs only to the if block, and is used only inside it.

Try This

This code breaks. Predict the error, then fix it by moving one declaration.

What this code doesPractise: this code breaks because of scope. Find out why before you fix it.
app.js
1
2
3
4
5
6
7
8
9
10
// It is nine in the morning
const hour = 9;

if (hour < 12) {
  // greeting is declared inside the block
  const greeting = 'Good morning';
}

// Trying to use it outside the block
console.log(greeting);
OUTPUT   TERMINAL
➜ webbo3 node app.js
ReferenceError: greeting is not defined

Fixed version:

What this code doesThe fixed version: declare greeting before the block, so it can be used after it.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// It is nine in the morning
const hour = 9;

// Declare greeting before the if, so it lives outside the block
let greeting;

// Assign it inside the branches
if (hour < 12) {
  greeting = 'Good morning';
} else {
  greeting = 'Good afternoon';
}

// Now it can be used here
console.log(greeting);
OUTPUT   TERMINAL
➜ webbo3 node app.js
Good morning
Picture This

Picture a house. What you leave in the living room (global) anyone in the house can use. What you keep in your bedroom (a function) only people in that room can see. What you put in a drawer inside the bedroom (a block) is visible only when that drawer is open.

Do This Now

Now bring everything together. Do not just read these. Write each one yourself, predict the output, and then run it.

1. Adult or Not (Very Easy)

Write isAdult(age) that returns true for 18 and above, and false otherwise.

What this code doesExercise 1: answer one yes-or-no question about an age, from inside a function.
app.js
1
2
3
4
5
6
7
8
9
// true for 18 and above, false otherwise
function isAdult(age) {
  // The comparison itself is the answer, so return it directly
  return age >= 18;
}

// Test one adult and one child
console.log(isAdult(21));
console.log(isAdult(15));
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
false

2. Delivery Fee (Simple Application)

A shop delivers free for orders of N20,000 or more. Smaller orders pay N1,500.

What this code doesExercise 2: charge a delivery fee only on orders below N20,000.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
// Work out the delivery fee for an order total
function deliveryFee(orderTotal) {
  // Big orders deliver free
  if (orderTotal >= 20000) {
    return 0;
  }
  // Everything else pays the standard fee
  return 1500;
}

// Test a big order and a small one
console.log(deliveryFee(25000));
console.log(deliveryFee(8000));
OUTPUT   TERMINAL
➜ webbo3 node app.js
0
1500

3. Ticket Price (Combination)

Weekend tickets cost N3,000 and weekday tickets N2,000. Students get N500 off. Use a switch, a condition and a default parameter together.

What this code doesExercise 3: combine a switch, a condition and a default parameter to price a ticket.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// isStudent is false unless the caller says otherwise
function ticketPrice(day, isStudent = false) {
  // The price is decided below, so start with no value
  let price;

  // Step 1: the base price depends on the day
  switch (day) {
    case 'saturday':
    case 'sunday':
      price = 3000;
      break;
    default:
      price = 2000;
  }

  // Step 2: students get N500 off
  if (isStudent) {
    price = price - 500;
  }

  // Step 3: hand the final price back
  return price;
}

console.log(ticketPrice('sunday'));        // weekend, not a student
console.log(ticketPrice('sunday', true));  // weekend, student
console.log(ticketPrice('tuesday', true)); // weekday, student
OUTPUT   TERMINAL
➜ webbo3 node app.js
3000
2500
1500

4. The Student Result Analyzer (Small Real-World Problem)

This is your first piece of real business logic: rules a school actually has, expressed as functions. Build it as four small functions, not one long script.

  1. average(a, b, c) returns the average of three scores.
  2. gradeFor(avg) returns A, B, C or F: 70 and above is A, 60 is B, 50 is C.
  3. verdict(avg, attendance) returns "Pass" only when the average is 50 or more and attendance is 0.75 or more, "Withheld" when the average passes but attendance does not, and "Fail" otherwise.
  4. report(name, a, b, c, attendance) puts it all together in one line.
What this code doesExercise 4: turn a school's result rules into four small functions that work together.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 1. Add the three scores and divide by three
function average(a, b, c) {
  return (a + b + c) / 3;
}

// 2. Turn an average into a grade letter, strictest first
function gradeFor(avg) {
  if (avg >= 70) return 'A';
  if (avg >= 60) return 'B';
  if (avg >= 50) return 'C';
  return 'F';
}

// 3. Apply the school's pass rule
function verdict(avg, attendance) {
  // Name the two conditions
  const passed = avg >= 50;
  const attended = attendance >= 0.75;

  if (passed && attended) return 'Pass';
  if (passed && !attended) return 'Withheld: attendance below 75%';
  return 'Fail';
}

// 4. Put everything together into one line
function report(name, a, b, c, attendance) {
  const avg = average(a, b, c);
  return `${name} | average ${avg} | grade ${gradeFor(avg)} | ${verdict(avg, attendance)}`;
}

// Run the analyser for three students
console.log(report('Chidinma', 72, 66, 90, 0.9));
console.log(report('Musa', 55, 61, 58, 0.5));
console.log(report('Tunde', 30, 44, 40, 0.95));
OUTPUT   TERMINAL
➜ webbo3 node app.js
Chidinma | average 76 | grade A | Pass
Musa | average 58 | grade C | Withheld: attendance below 75%
Tunde | average 38 | grade F | Fail
Extend It Tonight

Add a rule of your own: for example, a student whose average is 85 or more gets "Pass with distinction". Make it fit the existing functions without rewriting them. If one new rule forces you to change three functions, each function is doing too much. That feeling is the lesson.

Checkpoint

Q1. Why must a grade chain start at 70 rather than at 50?

Because the first true branch wins. Starting at 50 catches every passing score in the first branch, so the higher grades are never reached.

Q2. A function has no return. What do you get when you call it?

undefined. It ran, it may even have printed something, but it handed nothing back.

What this code doesCheck your answer: call a function that has no return.
app.js
1
2
3
4
5
6
7
// A function that does some work but has no return
function noReturn() {
  const x = 5;
}

// Print what the call hands back
console.log(noReturn());
OUTPUT   TERMINAL
➜ webbo3 node app.js
undefined
Q3. Why is vat = 7.5 as a default parameter safer than vat || 7.5?

A default parameter only fills in for undefined. || replaces every falsy value, so a genuine 0 would be thrown away and replaced by 7.5.

Q4. Name a value that is truthy but that beginners expect to be falsy.

The string '0', the string 'false', or an empty array [].

What this code doesCheck your answer: judge three values that beginners often get wrong.
app.js
1
2
3
4
// Three values beginners often expect to be falsy
console.log(Boolean('0'));     // the text "0"
console.log(Boolean('false')); // the text "false"
console.log(Boolean([]));      // an empty array
OUTPUT   TERMINAL
➜ webbo3 node app.js
true
true
true
Q5. What does this switch print, and why?

Both lines, because case 2 has no break, so it falls through into case 3.

What this code doesCheck your answer: a switch where one case has no break.
app.js
1
2
3
4
5
6
7
8
9
10
11
// The menu option pressed
const option = 2;

switch (option) {
  case 2:
    console.log('Buy airtime');
    // no break here
  case 3:
    console.log('Buy data');
    break;
}
OUTPUT   TERMINAL
➜ webbo3 node app.js
Buy airtime
Buy data
Q6. Why does this code throw an error?

total was declared with const inside the if block, so it only exists inside those braces. Declare it before the block to use it afterwards.

What this code doesCheck your answer: use a variable outside the block it was declared in.
app.js
1
2
3
4
5
6
7
if (true) {
  // total only exists inside these braces
  const total = 100;
}

// Trying to use it outside them
console.log(total);
OUTPUT   TERMINAL
➜ webbo3 node app.js
ReferenceError: total is not defined

Tick Before You Move On

  • ☐ I can write a condition with comparison operators
  • ☐ I can combine conditions with &&, || and !
  • ☐ I name my conditions instead of writing one long line
  • ☐ I understand why the order of an if chain matters
  • ☐ I know the six falsy values and the empty-field trap
  • ☐ I can use switch, and I never forget break by accident
  • ☐ I know the difference between return and console.log
  • ☐ I can write a function in all three styles
  • ☐ I use default parameters instead of ||
  • ☐ I understand global, function and block scope
  • ☐ I built the Student Result Analyzer as four functions

Quick Recap

A condition is a yes-or-no question, built with comparison operators and combined with &&, || and !. An if chain runs the first branch that is true, so the strictest condition goes first. Six values are falsy and everything else is truthy, which is why a typed 0 can be rejected by mistake. switch compares one value against exact options, and needs break to stop. A function is written once and called many times, and return hands its result back. Default parameters fill in only for undefined, so they keep a real 0. Scope decides where a variable exists: declare it at the level where you need to use it.

Final Scenario

Imagine the school asks you to automate its admission list tomorrow.

For every applicant, the program has to check a score and a payment, decide admitted or not, and print one clear line. The same rules must apply to every applicant, and when the school changes the pass mark, you should only have to change it once.

You now have every piece:

  • Conditions to ask the questions.
  • if and else to act on the answers.
  • A function so the rules are written once.
  • A default parameter for the usual case.
  • A global pass mark that every call can read.
What this code doesWe want to apply one admission rule to every applicant, with the pass mark written in a single place.
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// One pass mark, read by every call
const passMark = 50;

// feePaid defaults to false when it is not passed
function admission(name, score, feePaid = false) {
  // Name the score question
  const passed = score >= passMark;

  // Passed and paid: fully admitted
  if (passed && feePaid) {
    return `${name}: Admitted`;
  // Passed but not yet paid
  } else if (passed) {
    return `${name}: Passed, awaiting fee`;
  }

  // Did not pass
  return `${name}: Not admitted`;
}

// Three applicants
console.log(admission('Aisha', 68, true));
console.log(admission('Bayo', 74));
console.log(admission('Ngozi', 42, true));
OUTPUT   TERMINAL
➜ webbo3 node app.js
Aisha: Admitted
Bayo: Passed, awaiting fee
Ngozi: Not admitted

That is the mental model to carry forward. Your code no longer just calculates. It asks questions, takes different paths depending on the answers, and keeps each rule in one named place you can call again and again.

Tomorrow, Day 3: Arrays, objects and reshaping data. Today you analysed three students by passing their scores in one at a time. Tomorrow you will hold a whole class of students in one value, and run these same functions over all of them at once.

Learn this with a real instructor

Free lessons take you a long way on your own. The full programmes add live classes, assignments, Skill Points and a certificate — built for African students.