JavaScript · Lesson 09

JavaScript Functions: JS Functions · Function Intro · Invocation · Parameters · Return · Arguments · Expressions · Arrow Functions · Function Quiz

18 phases  ·  Build: 🏫 Project Overview

👋 Welcome to Lesson 09

Work through each phase in order. Complete the task before unlocking the next. Your Build It project unlocks when all phases are done.

📚 18 phases🏗️ 🏫 Project Overview🌐 GitHub Pages
Phase 1 of 18
1. What Is a Function? The Big Picture

The Problem That Functions Solve

Imagine you are a baker. Every morning you make bread. The steps are always the same: measure flour, add water, knead, bake. Without functions, your recipe book would look like this:

code
Monday:   Measure flour. Add water. Knead. Bake.
Tuesday:  Measure flour. Add water. Knead. Bake.
Wednesday: Measure flour. Add water. Knead. Bake.
...

That is repetitive and hard to update. What if you want to change the temperature? You'd have to edit every single day.

With a function, your recipe book says:

code
Define BAKE_BREAD: Measure flour. Add water. Knead. Bake.

Monday:    BAKE_BREAD
Tuesday:   BAKE_BREAD
Wednesday: BAKE_BREAD

Now if you change the temperature, you change it in ONE place and every day automatically updates.

This is exactly what functions do in programming: they define a task once and let you run it as many times as needed, anywhere in your code.

What Is a Function?

A function is a named, reusable block of code that:

  1. Is defined once (you write the instructions)
  2. Is called/invoked whenever you need it (you run those instructions)
  3. Can receive inputs (parameters)
  4. Can return an output (a result)

Why Functions Are Central to Programming

Every programming job requires functions. They are the backbone of:

  • Web apps: A function runs every time a button is clicked
  • APIs: Functions process incoming requests and send responses
  • Data analysis: Functions clean, transform, and summarize datasets
  • Games: Functions handle player movement, collisions, score updates
  • Automation: Functions perform tasks like sending emails, resizing images

A program without functions is like a city with no roads · you'd have to rebuild every path from scratch every time.

Real-World Analogy

Think of a function like a vending machine:

  • You insert money (inputs/arguments)
  • The machine processes your request (function body)
  • It gives you a snack (return value)
  • The machine can be used again and again without rebuilding it

✏️ Your Task
### What Is a Function? A function is a named, reusable block of code that: 1. Is defined once (you write the instructions) 2. Is called/invoked whenever you need it (you run those instructions) 3. Can receive inputs (parameters) 4. Can return an output (a result)
Phase 2 of 18
2. Defining a Function · Syntax and Structure

The Basic Syntax

javascript
function functionName(parameter1, parameter2) {
  // Code to execute — the "function body"
  // ...
  return result;  // optional: send a value back
}

Let's break down each piece:

PartWhat It Means
functionThe keyword that tells JavaScript: "I'm defining a function"
functionNameThe name you give it · use it later to call the function
(parameter1, parameter2)The parameter list · placeholders for input values
{ ... }The function body · the code that runs when called
return resultOptional · sends a value back to whoever called it

Your First Function

javascript
// Define the function:
function greet() {
  console.log("Hello, World!");
}

// Call (invoke) the function:
greet();  // Output: Hello, World!
greet();  // Output: Hello, World!  (runs again — reusable!)

Step-by-step:

  1. function greet() · creates a function named greet with no parameters
  2. { console.log("Hello, World!"); } · the body: one instruction to print text
  3. greet(); · calling the function using its name followed by ()
  4. The function runs and prints the message

⚠️ Common Beginner Mistake: Defining a function but forgetting to CALL it. Defining just sets it up · it does NOT run until you call it with ().

javascript
// This defines but does NOT run the function:
function sayHi() { console.log("Hi!"); }

// This RUNS the function:
sayHi();  // Output: Hi!

A Function with Parameters

javascript
// Define a function with parameters:
function greetPerson(name) {
  console.log("Hello, " + name + "!");
}

// Call with different inputs:
greetPerson("Alice");   // Output: Hello, Alice!
greetPerson("Bob");     // Output: Hello, Bob!
greetPerson("Chidi");   // Output: Hello, Chidi!

name is a parameter · a placeholder that receives the value passed in when the function is called.

A Function with a Calculation

javascript
function multiply(a, b) {
  let result = a * b;
  return result;
}

let answer = multiply(5, 3);
console.log(answer);          // 15
console.log(multiply(10, 7)); // 70

Step-by-step for multiply(5, 3):

  1. Function is called with values 5 and 3
  2. Inside: a = 5, b = 3
  3. result = 5 * 3 = 15
  4. return 15 · sends 15 back to the caller
  5. answer now holds 15

Naming Functions · Best Practices

Function names should describe what the function does, using camelCase (first word lowercase, subsequent words capitalized):

javascript
// ✅ Good function names — clear and descriptive:
function calculateTax() { ... }
function getUserAge() { ... }
function sendEmailNotification() { ... }
function isValidEmail() { ... }    // starts with 'is' = returns true/false

// ❌ Bad function names — vague or confusing:
function doStuff() { ... }
function x() { ... }
function function1() { ... }

✏️ Your Task
Practise what you just learned about 2. Defining a Function · Syntax and Structure. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 3 of 18
3. Calling (Invoking) a Function · Making It Run

What Does "Calling" Mean?

Calling a function means telling JavaScript: "Run this function right now." You do this by writing the function name followed by parentheses ().

javascript
function sayGoodMorning() {
  console.log("Good morning!");
}

// Without calling — nothing happens:
sayGoodMorning;    // ← No parentheses = doesn't run, just references the function

// With calling — it runs:
sayGoodMorning();  // Output: Good morning!

🤔 Thinking question: What is the difference between sayGoodMorning and sayGoodMorning()? Answer: Without (), you are referring to the function itself as a value. With (), you are EXECUTING it.

Calling with Arguments

When you call a function with inputs, those inputs are called arguments:

javascript
function add(a, b) {           // a and b are PARAMETERS (in the definition)
  return a + b;
}

let sum = add(10, 25);         // 10 and 25 are ARGUMENTS (in the call)
console.log(sum);              // 35

Calling a Function from Another Function

Functions can call other functions · this is how complex programs are built from simple pieces:

javascript
function square(n) {
  return n * n;
}

function sumOfSquares(a, b) {
  return square(a) + square(b);   // calls square() twice
}

console.log(sumOfSquares(3, 4));  // 9 + 16 = 25
console.log(sumOfSquares(5, 12)); // 25 + 144 = 169

Calling a Function Before It Is Defined

With regular function declarations (using the function keyword), you can call them BEFORE they are written in the code. This is called hoisting (covered in Section 12):

javascript
console.log(double(5));   // 10  ← Works! Even though double is defined below

function double(n) {
  return n * 2;
}

✏️ Your Task
Practise what you just learned about 3. Calling (Invoking) a Function · Making It Run. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 4 of 18
4. The Four Ways to Invoke a Function

JavaScript has four distinct ways a function can be invoked (called). The difference matters because each affects what the this keyword refers to inside the function.

Way 1 · As a Regular Function Call

The most common way: calling the function by name:

javascript
function greet() {
  console.log("Hello!");
}
greet();  // Output: Hello!

In strict mode ("use strict"), this inside is undefined. In non-strict mode, this is the global object (window in a browser).

javascript
function showThis() {
  console.log(this);
}
showThis();  // In browser: window object (or undefined in strict mode)

Way 2 · As a Method (Function Inside an Object)

When a function belongs to an object, it becomes a method. this refers to that object:

javascript
const person = {
  name: "Alice",
  greet: function() {
    console.log("Hello, I am " + this.name);
  }
};

person.greet();  // Output: Hello, I am Alice
// 'this' = the person object
javascript
// Another example:
const calculator = {
  value: 0,
  add: function(n) {
    this.value += n;
    return this;  // allows chaining
  },
  multiply: function(n) {
    this.value *= n;
    return this;
  },
  result: function() {
    console.log(this.value);
  }
};

calculator.add(5).multiply(3).result();  // 15

Way 3 · As a Constructor (Using new)

When a function is called with new, it creates a brand-new object. this refers to that new object. These are called constructor functions:

javascript
function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName  = lastName;
  this.age       = age;
}

// 'new' creates a new object:
let person1 = new Person("John", "Doe", 30);
let person2 = new Person("Mary", "Smith", 25);

console.log(person1.firstName);  // John
console.log(person2.age);        // 25

Step-by-step for new Person("John", "Doe", 30):

  1. A new empty object {} is created
  2. this is set to that new object
  3. this.firstName = "John" · sets a property on the new object
  4. The new object is automatically returned

By convention, constructor functions start with a Capital Letter to distinguish them from regular functions.

Way 4 · Via call(), apply(), or bind() (Explicit Invocation)

These methods let you control exactly what this refers to. This is an advanced topic · here is a glimpse:

javascript
function introduce(city, country) {
  console.log(`I am ${this.name} from ${city}, ${country}.`);
}

const user = { name: "Amara" };

// call() — invoke immediately, pass args individually:
introduce.call(user, "Lagos", "Nigeria");
// Output: I am Amara from Lagos, Nigeria.

// apply() — invoke immediately, pass args as an array:
introduce.apply(user, ["Accra", "Ghana"]);
// Output: I am Amara from Accra, Ghana.

// bind() — returns a NEW function with 'this' fixed:
const boundIntro = introduce.bind(user);
boundIntro("Nairobi", "Kenya");
// Output: I am Amara from Nairobi, Kenya.

✏️ Your Task
Practise what you just learned about 4. The Four Ways to Invoke a Function. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 5 of 18
5. Parameters vs. Arguments · Know the Difference

These two terms are often confused. Here is the definitive rule:

TermWhere?Meaning
ParameterIn the function DEFINITIONThe placeholder variable name
ArgumentIn the function CALLThe actual value being passed
javascript
//                  Parameters ↓       ↓
function calculateArea(length, width) {
  return length * width;
}

//          Arguments ↓    ↓
let area = calculateArea(10, 5);
console.log(area);  // 50

Think of it this way:

  • Parameter = the label on a mailbox slot (the slot exists even when empty)
  • Argument = the letter you put in that slot (the actual piece of mail)

What Happens with Too Many or Too Few Arguments?

JavaScript is flexible · it does NOT crash if you pass the wrong number of arguments:

javascript
function greet(name, greeting) {
  console.log(greeting + ", " + name + "!");
}

// Too few arguments:
greet("Alice");
// greeting = undefined
// Output: "undefined, Alice!"  ← Might not be what you want!

// Too many arguments:
greet("Alice", "Hello", "Extra", "Ignored");
// Extra args are simply ignored
// Output: "Hello, Alice!"

⚠️ Common Beginner Mistake: Forgetting that missing arguments become undefined, not 0 or "". Always provide default values for optional parameters.

Parameter Rules

  • Parameters are local variables · they only exist inside the function
  • Each parameter is separated by a comma
  • There is no limit on how many parameters a function can have
  • Parameter names must follow variable naming rules (no spaces, no reserved words)
javascript
// Parameters are LOCAL — not accessible outside:
function doubleIt(x) {
  let doubled = x * 2;
  return doubled;
}
doubleIt(5);
// console.log(x);       // ❌ ReferenceError: x is not defined
// console.log(doubled); // ❌ ReferenceError: doubled is not defined

✏️ Your Task
Practise what you just learned about 5. Parameters vs. Arguments · Know the Difference. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 6 of 18
6. Default Parameter Values

The Problem

When a caller forgets to pass an argument, the parameter becomes undefined. This can cause bugs:

javascript
function greet(name) {
  console.log("Hello, " + name + "!");
}
greet();         // Output: "Hello, undefined!"  ← Bug!

The Old Way (Before ES6)

Before modern JavaScript, developers used the || operator to set fallback values:

javascript
function greet(name) {
  name = name || "Guest";  // if name is falsy, use "Guest"
  console.log("Hello, " + name + "!");
}
greet();          // Output: Hello, Guest!
greet("Alice");   // Output: Hello, Alice!

Problem with ||: If you pass 0 or false as a legitimate value, it still falls back to the default (because 0 and false are falsy).

The Modern Way · ES6 Default Parameters

ES6 (2015) introduced default parameter values directly in the function definition:

javascript
function greet(name = "Guest") {
  console.log("Hello, " + name + "!");
}
greet();           // Output: Hello, Guest!    (default used)
greet("Alice");    // Output: Hello, Alice!    (argument used)
greet(undefined);  // Output: Hello, Guest!    (undefined triggers default)
greet(null);       // Output: Hello, null!     (null does NOT trigger default)

Multiple Default Parameters

javascript
function createProfile(name = "Anonymous", age = 0, city = "Unknown") {
  return `${name}, Age: ${age}, City: ${city}`;
}

console.log(createProfile());
// Output: Anonymous, Age: 0, City: Unknown

console.log(createProfile("Alice"));
// Output: Alice, Age: 0, City: Unknown

console.log(createProfile("Bob", 30, "Lagos"));
// Output: Bob, Age: 30, City: Lagos

Default Parameters Using Expressions

Default values can be any valid expression, including function calls:

javascript
function getDate() {
  return new Date().getFullYear();
}

function createUser(name, year = getDate()) {
  console.log(`${name} joined in ${year}`);
}

createUser("Alice");         // Output: Alice joined in 2025
createUser("Bob", 2022);     // Output: Bob joined in 2022

Real-World Use

javascript
// E-commerce: Order with optional discount and currency:
function placeOrder(item, price, discount = 0, currency = "NGN") {
  let finalPrice = price * (1 - discount);
  return `Order: ${item} | Price: ${currency} ${finalPrice.toFixed(2)}`;
}

console.log(placeOrder("Laptop", 250000));
// Output: Order: Laptop | Price: NGN 250000.00

console.log(placeOrder("Laptop", 250000, 0.1));
// Output: Order: Laptop | Price: NGN 225000.00

console.log(placeOrder("Phone", 80000, 0.05, "USD"));
// Output: Order: Phone | Price: USD 76000.00

✏️ Your Task
Practise what you just learned about 6. Default Parameter Values. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 7 of 18
7. The `return` Statement · Getting Results Back

What Is return?

The return statement does two things simultaneously:

  1. Sends a value back to whoever called the function
  2. Immediately exits the function · no more code inside the function runs
javascript
function add(a, b) {
  return a + b;      // ← sends the sum back, then exits
  console.log("This never runs");  // ← NEVER executes
}

let result = add(3, 7);
console.log(result);   // 10

Functions Without return

If a function has no return statement, it returns undefined automatically:

javascript
function printHello() {
  console.log("Hello!");
  // no return statement
}

let output = printHello();
console.log(output);   // undefined

This is fine for functions that just do something (like printing or updating a display) rather than produce a value.

Early Return · Exiting a Function Early

return can appear multiple times in a function and can be used to exit early when a condition is met:

javascript
function divide(a, b) {
  if (b === 0) {
    return "Cannot divide by zero!";  // exits here if b is 0
  }
  return a / b;   // only reached if b !== 0
}

console.log(divide(10, 2));   // 5
console.log(divide(10, 0));   // Cannot divide by zero!

Step-by-step for divide(10, 0):

  1. b === 0 is true
  2. Return "Cannot divide by zero!" immediately
  3. The function exits · return a / b is NEVER reached

Returning Multiple Values (Via an Object or Array)

A function can only return ONE value, but that value can be an object or array containing multiple pieces of data:

javascript
// Return multiple values via object:
function getMinMax(numbers) {
  let min = Math.min(...numbers);
  let max = Math.max(...numbers);
  return { min: min, max: max };   // one object containing two values
}

let stats = getMinMax([3, 1, 7, 2, 9, 4]);
console.log(stats.min);    // 1
console.log(stats.max);    // 9
console.log(stats);        // { min: 1, max: 9 }

// Return multiple values via array:
function splitName(fullName) {
  let parts = fullName.split(" ");
  return [parts[0], parts[parts.length - 1]];
}

let [firstName, lastName] = splitName("Chukwuemeka Obi");
console.log(firstName);  // Chukwuemeka
console.log(lastName);   // Obi

Real-World Use

javascript
// Grade calculation — uses early returns to categorize scores:
function getGrade(score) {
  if (score < 0 || score > 100) return "Invalid score";
  if (score >= 90) return "A";
  if (score >= 75) return "B";
  if (score >= 60) return "C";
  if (score >= 45) return "D";
  return "F";
}

console.log(getGrade(95));   // A
console.log(getGrade(72));   // B
console.log(getGrade(58));   // C
console.log(getGrade(30));   // F
console.log(getGrade(-5));   // Invalid score

✏️ Your Task
Practise what you just learned about 7. The return Statement · Getting Results Back. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 8 of 18
8. Functions as Values · Storing and Passing Functions

Functions Are First-Class Citizens

In JavaScript, functions are values just like numbers, strings, and arrays. This means you can:

  • Store a function in a variable
  • Pass a function as an argument to another function
  • Return a function from another function

This is one of JavaScript's most powerful features.

Storing a Function in a Variable

javascript
// Store a function reference in a variable:
function double(n) { return n * 2; }

let myFunc = double;       // No () — we're storing, not calling!

console.log(myFunc(5));    // 10  (calling via the variable)
console.log(double(5));    // 10  (same result)

Passing a Function as an Argument

A function that receives another function as an argument is called a higher-order function. The function being passed in is called a callback:

javascript
function applyOperation(a, b, operation) {
  return operation(a, b);    // calls whatever function was passed in
}

function add(x, y) { return x + y; }
function multiply(x, y) { return x * y; }
function subtract(x, y) { return x - y; }

console.log(applyOperation(5, 3, add));       // 8
console.log(applyOperation(5, 3, multiply));  // 15
console.log(applyOperation(5, 3, subtract));  // 2

Real-world example · Array method forEach uses callbacks:

javascript
let scores = [85, 72, 91, 60, 88];

// forEach passes each element to the callback function:
scores.forEach(function(score) {
  console.log(`Score: ${score} → Grade: ${getGrade(score)}`);
});
// Output:
// Score: 85 → Grade: B
// Score: 72 → Grade: B
// Score: 91 → Grade: A
// Score: 60 → Grade: C
// Score: 88 → Grade: B

✏️ Your Task
Practise what you just learned about 8. Functions as Values · Storing and Passing Functions. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 9 of 18
9. The `arguments` Object · Handling Unknown Numbers of Inputs

What Is the arguments Object?

Inside every regular function (not arrow functions), JavaScript automatically creates a special object called arguments. It contains ALL the values passed in during the call, even if they exceed the number of defined parameters.

Think of arguments as an automatic guest list · it records everyone who showed up, even if you only expected a few.

javascript
function showAll() {
  console.log(arguments);
  console.log(arguments.length);
  console.log(arguments[0]);
}

showAll("Alice", 30, "Lagos");
// Output:
// Arguments(3) ["Alice", 30, "Lagos"]   (array-like object)
// 3
// Alice

arguments Is Array-Like (But NOT an Array)

It has indices and a length property, but it lacks standard array methods like .forEach(), .map(), .filter(). You can convert it to a real array:

javascript
function sumAll() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}

console.log(sumAll(1, 2, 3));          // 6
console.log(sumAll(10, 20, 30, 40));   // 100
console.log(sumAll(5));                // 5

Real-World Use

javascript
// A flexible logger function that accepts any number of messages:
function log() {
  let timestamp = new Date().toLocaleTimeString();
  let messages = Array.from(arguments).join(" | ");
  console.log(`[${timestamp}] ${messages}`);
}

log("User logged in", "ID: 42");
log("Page loaded", "URL: /dashboard", "Time: 1.2s");
// Output:
// [10:34:22 AM] User logged in | ID: 42
// [10:34:22 AM] Page loaded | URL: /dashboard | Time: 1.2s

The Modern Alternative · Rest Parameters ...args

ES6 introduced rest parameters, which are a cleaner, more powerful replacement for the arguments object. Rest parameters give you a REAL array:

javascript
function sumAll(...numbers) {    // ...numbers collects ALL arguments into a real array
  let total = 0;
  for (let n of numbers) {
    total += n;
  }
  return total;
}

console.log(sumAll(1, 2, 3));         // 6
console.log(sumAll(10, 20, 30, 40));  // 100

// Now you can use real array methods:
function maxOf(...numbers) {
  return Math.max(...numbers);   // spread the array into Math.max
}
console.log(maxOf(3, 1, 9, 5, 7));  // 9

Mixing regular parameters with rest:

javascript
function greetMany(greeting, ...names) {
  names.forEach(name => console.log(`${greeting}, ${name}!`));
}

greetMany("Hello", "Alice", "Bob", "Charlie");
// Output:
// Hello, Alice!
// Hello, Bob!
// Hello, Charlie!

Best practice: Use rest parameters (...args) instead of the arguments object in modern JavaScript. Rest parameters work in arrow functions, are real arrays, and are clearer.


✏️ Your Task
Practise what you just learned about 9. The arguments Object · Handling Unknown Numbers of Inputs. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 10 of 18
10. Arguments Are Passed by Value vs. by Reference

Passed by Value · Primitives (Numbers, Strings, Booleans)

When you pass a primitive value (number, string, boolean) to a function, JavaScript passes a copy. Changing it inside the function does NOT affect the original:

javascript
function changeValue(x) {
  x = 100;                    // changes the LOCAL copy only
  console.log("Inside:", x);  // 100
}

let myNum = 5;
changeValue(myNum);
console.log("Outside:", myNum);  // 5  ← UNCHANGED!

Why? Because myNum and x are separate variables. x gets a copy of 5, not a connection to myNum.

Passed by Reference · Objects and Arrays

When you pass an object or array, JavaScript passes a reference (think: the address of where the object lives in memory). Changes inside the function AFFECT the original:

javascript
function changeObjectProperty(obj) {
  obj.name = "Bob";         // changes the ACTUAL object
}

let person = { name: "Alice", age: 30 };
changeObjectProperty(person);
console.log(person.name);  // "Bob"  ← CHANGED!
javascript
// Same with arrays:
function addItem(arr) {
  arr.push("newItem");
}

let myArray = ["a", "b", "c"];
addItem(myArray);
console.log(myArray);  // ["a", "b", "c", "newItem"]  ← CHANGED!

⚠️ Common Beginner Mistake: Not realizing that passing objects to functions can accidentally modify the original. To be safe, clone the object first:

javascript
// Safe: clone before modifying:
function updateName(obj, newName) {
  let copy = { ...obj };    // spread operator creates a shallow copy
  copy.name = newName;
  return copy;              // return new object, original untouched
}

let user = { name: "Alice", age: 30 };
let updated = updateName(user, "Bob");
console.log(user.name);     // "Alice"  ← safe, unchanged
console.log(updated.name);  // "Bob"

✏️ Your Task
Practise what you just learned about 10. Arguments Are Passed by Value vs. by Reference. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 11 of 18
11. Function Expressions · Unnamed Functions in Variables

What Is a Function Expression?

A function expression is when you define a function and immediately store it in a variable. The function itself can be anonymous (unnamed):

javascript
// Function DECLARATION (has a name):
function add(a, b) {
  return a + b;
}

// Function EXPRESSION (stored in a variable, function is anonymous):
const add = function(a, b) {
  return a + b;
};

// Both work the same way when called:
console.log(add(3, 4));  // 7

Named Function Expressions

You can also give a name to the function in an expression (useful for recursion or debugging):

javascript
const factorial = function calculateFactorial(n) {
  if (n <= 1) return 1;
  return n * calculateFactorial(n - 1);  // can call itself by name
};

console.log(factorial(5));  // 120
// calculateFactorial(5);    // ❌ Not accessible outside the expression

The Key Difference: Hoisting

Function DECLARATIONS are hoisted (available before they are defined). Function EXPRESSIONS are NOT:

javascript
// ✅ Declaration — can call BEFORE it's defined:
console.log(square(4));   // 16
function square(n) { return n * n; }

// ❌ Expression — CANNOT call before it's defined:
// console.log(cube(3));  // TypeError: cube is not a function
const cube = function(n) { return n * n * n; };
console.log(cube(3));     // 27  (fine after the definition)

When to Use Function Expressions

Function expressions are ideal when:

  1. You want to pass a function as an argument
  2. You want to assign different functions conditionally
  3. You want to ensure the function isn't accidentally called before it's ready
javascript
// Conditional function assignment:
let greet;
if (language === "fr") {
  greet = function(name) { return `Bonjour, ${name}!`; };
} else {
  greet = function(name) { return `Hello, ${name}!`; };
}
console.log(greet("Alice"));

✏️ Your Task
Practise what you just learned about 11. Function Expressions · Unnamed Functions in Variables. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 12 of 18
12. Hoisting · Why Declaration Order Matters

What Is Hoisting?

Hoisting is JavaScript's behavior of moving function and variable declarations to the TOP of their scope before the code runs. Think of it like JavaScript secretly reading your whole file first, noting all the function names, then running the code.

javascript
// Even though greet is defined at the BOTTOM, this still works:
greet("World");   // Output: Hello, World!

function greet(name) {
  console.log("Hello, " + name + "!");
}

Behind the scenes · JavaScript actually processes this as:

javascript
// JavaScript internally reorders to:
function greet(name) {          // ← moved to top
  console.log("Hello, " + name + "!");
}
greet("World");                 // ← then this runs

Only Declarations Are Hoisted · Not Expressions

javascript
// ✅ Declaration — fully hoisted:
sayHello();   // Works!
function sayHello() { console.log("Hello!"); }

// ❌ Expression with var — variable hoisted but set to undefined:
sayBye();     // TypeError: sayBye is not a function
var sayBye = function() { console.log("Bye!"); };

// ❌ Expression with let/const — NOT hoisted at all:
sayHi();      // ReferenceError: Cannot access 'sayHi' before initialization
const sayHi = function() { console.log("Hi!"); };

Best practice: Even though declarations are hoisted, define functions before you use them. It makes code more readable and predictable. Rely on hoisting sparingly.


✏️ Your Task
Practise what you just learned about 12. Hoisting · Why Declaration Order Matters. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 13 of 18
13. Arrow Functions · The Modern Shorthand

What Are Arrow Functions?

Arrow functions were introduced in ES6 (2015) and provide a shorter, cleaner syntax for writing functions. They use the => symbol (the "arrow").

Think of arrow functions as a streamlined sports car compared to the full-featured regular function truck · faster to write, sleeker to read, but with a few differences you need to know.

Syntax Progression · From Long to Short

Let's evolve the same function through all the arrow function shorthand options:

Step 1 · Traditional function expression:

javascript
const double = function(n) {
  return n * 2;
};

Step 2 · Arrow function (full):

javascript
const double = (n) => {
  return n * 2;
};

Step 3 · Arrow function with implicit return (if body is a single expression, skip {} and return):

javascript
const double = (n) => n * 2;

Step 4 · Arrow function with single parameter (skip parentheses):

javascript
const double = n => n * 2;

All four versions work identically:

javascript
console.log(double(5));   // 10

When You Can Drop the Parentheses Around Parameters

SituationExample
No parameters() => expression · parentheses REQUIRED
One parametern => expression · parentheses optional
Two+ parameters(a, b) => expression · parentheses REQUIRED
javascript
const greet    = () => "Hello!";             // No params — need ()
const double   = n => n * 2;                // One param — () optional
const add      = (a, b) => a + b;           // Two params — need ()
const describe = (name, age) => `${name} is ${age} years old`;

When You Must Keep the Curly Braces {}

If the function body has more than one statement, you MUST keep {} and use explicit return:

javascript
// ❌ This doesn't work — two statements need curly braces:
const gradeStudent = score => let grade = score >= 60 ? "Pass" : "Fail"; return grade;

// ✅ Correct — use curly braces and explicit return:
const gradeStudent = score => {
  let grade = score >= 60 ? "Pass" : "Fail";
  return grade;
};

console.log(gradeStudent(75));  // Pass
console.log(gradeStudent(40));  // Fail

Returning an Object Literal

If you want to return an object directly (without a function body), wrap it in parentheses to avoid confusion with the function body braces:

javascript
// ❌ JavaScript thinks {} is a function body, not an object:
const makeUser = name => { name: name };   // Returns undefined!

// ✅ Wrap the object in parentheses:
const makeUser = name => ({ name: name });
// Or shorthand property:
const makeUser = name => ({ name });

console.log(makeUser("Alice"));  // { name: "Alice" }

Arrow Functions in Practice

javascript
let numbers = [5, 2, 8, 1, 9, 3, 7];

// Sort ascending:
let ascending = numbers.sort((a, b) => a - b);
console.log(ascending);  // [1, 2, 3, 5, 7, 8, 9]

// Filter even numbers:
let evens = numbers.filter(n => n % 2 === 0);
console.log(evens);  // [2, 8]

// Map to squared values:
let squared = numbers.map(n => n * n);
console.log(squared);  // [25, 4, 64, 1, 81, 9, 49]

// Reduce to sum:
let total = numbers.reduce((acc, n) => acc + n, 0);
console.log(total);  // 35

Full Examples Compared

javascript
// Traditional:
function convertToUSD(nairaAmount) {
  const rate = 1500;
  return (nairaAmount / rate).toFixed(2);
}

// Arrow equivalent:
const convertToUSD = nairaAmount => (nairaAmount / 1500).toFixed(2);

console.log(convertToUSD(75000));   // "50.00"
console.log(convertToUSD(150000));  // "100.00"

✏️ Your Task
Practise what you just learned about 13. Arrow Functions · The Modern Shorthand. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 14 of 18
14. Arrow Functions and `this` · The Key Difference

The Biggest Difference Between Arrow and Regular Functions

Regular functions have their own this · it changes based on how they are called. Arrow functions do NOT have their own this · they inherit this from the surrounding code where they were defined. This is called lexical this.

The Problem Arrow Functions Solve

javascript
// ❌ Problem with regular function in setTimeout:
function Timer() {
  this.seconds = 0;

  setInterval(function() {
    this.seconds++;              // 'this' is NOT the Timer object here!
    console.log(this.seconds);  // NaN or undefined — wrong!
  }, 1000);
}

// ✅ Arrow function fixes it — inherits 'this' from Timer:
function Timer() {
  this.seconds = 0;

  setInterval(() => {
    this.seconds++;              // 'this' IS the Timer object
    console.log(this.seconds);  // 1, 2, 3, 4... — correct!
  }, 1000);
}

let t = new Timer();

Why? When setInterval calls a regular function, this becomes the global object (or undefined in strict mode). An arrow function doesn't rebind this · it captures the this from the enclosing Timer function.

Event Handlers · When NOT to Use Arrow Functions

javascript
// ❌ Arrow function in event handler loses element reference:
button.addEventListener("click", () => {
  console.log(this);        // Window (wrong — we want the button)
  this.classList.add("active");  // Fails!
});

// ✅ Regular function — 'this' refers to the element:
button.addEventListener("click", function() {
  console.log(this);        // The button element ✅
  this.classList.add("active");  // Works!
});

Arrow Functions Cannot Be Constructors

Because they lack their own this, arrow functions cannot be used with new:

javascript
const Person = (name) => {
  this.name = name;  // 'this' doesn't belong to arrow function
};

// ❌ This throws a TypeError:
// let p = new Person("Alice");  // TypeError: Person is not a constructor

Quick Reference · Regular vs. Arrow Functions

FeatureRegular FunctionArrow Function
this bindingOwn this (dynamic)Inherited from enclosing scope (lexical)
arguments object✅ Yes❌ No
Used as constructor✅ Yes (new)❌ No
Hoisted✅ Yes (declarations)❌ No
Best forMethods, constructors, event handlersCallbacks, array methods, short expressions
Syntaxfunction name() {}() => {}

✏️ Your Task
Practise what you just learned about 14. Arrow Functions and this · The Key Difference. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 15 of 18
15. Self-Invoking Functions (IIFE)

What Is an IIFE?

An IIFE (Immediately Invoked Function Expression · pronounced "iffy") is a function that defines itself AND runs immediately in the same statement. It runs ONCE and is never called again.

javascript
// Structure:
(function() {
  // code here runs immediately
})();

// Arrow function IIFE:
(() => {
  // code here runs immediately
})();

Why Use IIFE?

The main benefit is scope isolation · variables inside the IIFE are private and don't pollute the global scope:

javascript
// Without IIFE — pollutes global scope:
let counter = 0;   // now everyone can see and modify 'counter'

// With IIFE — counter is private:
(function() {
  let counter = 0;   // only exists inside here
  counter++;
  console.log("Counter:", counter);  // 1
})();

console.log(typeof counter);  // "undefined" — counter doesn't exist outside!

IIFE with Parameters

javascript
(function(name, year) {
  console.log(`Welcome, ${name}! This app was built in ${year}.`);
})("Alice", 2025);
// Output: Welcome, Alice! This app was built in 2025.

Real-World Use

IIFEs are used to:

  • Initialize a module or plugin without polluting global variables
  • Create private state in older JavaScript patterns
  • Run setup code exactly once (database connections, configuration)
javascript
// App initialization IIFE:
const app = (function() {
  let config = { theme: "dark", lang: "en" };  // private

  return {
    getTheme: () => config.theme,
    setTheme: (t) => { config.theme = t; }
  };
})();

console.log(app.getTheme());  // "dark"
app.setTheme("light");
console.log(app.getTheme());  // "light"
// config is never directly accessible from outside!

✏️ Your Task
Practise what you just learned about 15. Self-Invoking Functions (IIFE). Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 16 of 18
16. Functions Are Objects · Advanced Properties

Functions Have Properties

In JavaScript, functions ARE objects. This means they have built-in properties:

javascript
function greet(firstName, lastName) {
  return "Hello, " + firstName + " " + lastName;
}

console.log(typeof greet);     // "function"  (special type, but still an object)
console.log(greet.name);       // "greet"     (function's name)
console.log(greet.length);     // 2           (number of parameters)

function.name

Returns the function's name:

javascript
function add(a, b) { return a + b; }
const multiply = function(a, b) { return a * b; };
const square = n => n * n;

console.log(add.name);       // "add"
console.log(multiply.name);  // "multiply"   (inferred from variable name)
console.log(square.name);    // "square"     (inferred from variable name)

function.length

Returns the number of declared parameters (excluding rest parameters and those with defaults):

javascript
function f1(a, b, c) {}
function f2(a, b = 0) {}    // default params don't count
function f3(a, ...rest) {}  // rest params don't count

console.log(f1.length);  // 3
console.log(f2.length);  // 1  (only 'a' counts — 'b' has a default)
console.log(f3.length);  // 1  (only 'a' counts — rest doesn't count)

toString()

Returns the function's source code as a string:

javascript
function add(a, b) {
  return a + b;
}
console.log(add.toString());
// Output:
// "function add(a, b) {
//   return a + b;
// }"

✏️ Your Task
Practise what you just learned about 16. Functions Are Objects · Advanced Properties. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 17 of 18
17. Function Quiz · Test Your Knowledge

This section covers all the quiz-style questions from W3Schools' Function Quiz. Work through each one before reading the answer.


Q1. How do you call a function named myFunc?

code
A) myFunc
B) call myFunc()
C) myFunc()        ← ✅ CORRECT
D) myFunc[]

Explanation: Functions are called by writing their name followed by (). Without (), you just reference the function as a value without calling it.


Q2. How do you create a function in JavaScript?

code
A) function = myFunc() {}
B) function myFunc() {}     ← ✅ CORRECT
C) function:myFunc() {}
D) create myFunc() {}

Explanation: The function keyword comes first, then the name, then () for parameters, then {} for the body.


Q3. What is the correct way to write a function expression?

code
A) let x = function() {};         ← ✅ CORRECT
B) let x = new function() {};
C) function x = function() {};
D) let function x() {};

Explanation: A function expression assigns an anonymous function to a variable.


Q4. How do you use a function named celsius to convert from Fahrenheit to Celsius?

javascript
// Given:
function celsius(fahrenheit) {
  return (5/9) * (fahrenheit - 32);
}
code
A) celsius = (5/9) * (fahrenheit-32)
B) celsius(32)       ← ✅ CORRECT (pass the Fahrenheit value)
C) call celsius(32)
D) celsius.call(32)

Q5. What is the result of the following?

javascript
function addTen(num) {
  return num + 10;
}
let result = addTen(5);
code
A) 5
B) 10
C) 15        ← ✅ CORRECT
D) undefined

Q6. Which statement about the arguments object is true?

code
A) It works in arrow functions
B) It is available in all regular functions automatically    ← ✅ CORRECT
C) It is a real array
D) It must be declared manually

Explanation: arguments is automatically available in regular (non-arrow) functions. It is array-LIKE but not a real array.


Q7. What does this arrow function return?

javascript
const add = (a, b) => a + b;
console.log(add(3, 4));
code
A) undefined
B) 34
C) 7          ← ✅ CORRECT
D) Error

Explanation: Single-expression arrow functions have an implicit return. a + b = 3 + 4 = 7.


Q8. What is a self-invoking function?

code
A) A function that calls itself recursively
B) A function that runs automatically as soon as it is defined    ← ✅ CORRECT
C) A function that loops forever
D) A function inside an object

Q9. What will typeof return for a function?

javascript
function myFunc() {}
console.log(typeof myFunc);
code
A) "object"
B) "undefined"
C) "function"      ← ✅ CORRECT
D) "method"

Q10. What is the difference between function.length and arguments.length?

code
A) They are the same
B) function.length = number of declared parameters;
   arguments.length = number of arguments actually passed    ← ✅ CORRECT
C) function.length counts default params too
D) arguments.length only works in arrow functions

Q11. What does this return?

javascript
function test() {
  return;
  return 5;
}
console.log(test());
code
A) 5
B) undefined    ← ✅ CORRECT
C) null
D) Error

Explanation: The first return (with no value) exits the function immediately, returning undefined. The return 5 is never reached.


Q12. Which is the correct ES6 arrow function syntax?

code
A) function = () => {}
B) () =>: {}
C) const f = () => {}    ← ✅ CORRECT
D) const f => () {}

✏️ Your Task
Practise what you just learned about 17. Function Quiz · Test Your Knowledge. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 18 of 18
18. Applied Exercises

🏋️ Exercise 1 · Temperature Converter Library

Objective: Practice function definitions, parameters, default values, and return statements.

Real-world Scenario: A weather app needs to display temperatures in multiple units for users in different countries.

Warm-up Mini-Example:

javascript
// Simple conversion:
const celsiusToFahrenheit = c => (c * 9/5) + 32;
console.log(celsiusToFahrenheit(0));    // 32
console.log(celsiusToFahrenheit(100));  // 212

Your Exercise:

Write a conversion library with the following functions. Use arrow functions where appropriate.

Step-by-step Instructions:

  1. celsiusToFahrenheit(c) · convert Celsius to Fahrenheit: (C × 9/5) + 32
  2. fahrenheitToCelsius(f) · convert Fahrenheit to Celsius: (F − 32) × 5/9
  3. celsiusToKelvin(c) · convert Celsius to Kelvin: C + 273.15
  4. kelvinToCelsius(k) · convert Kelvin to Celsius: K − 273.15
  5. convertTemp(value, fromUnit = "C", toUnit = "F") · a master converter that calls the right function based on units
  6. All results rounded to 2 decimal places

Expected Output:

code
=== Temperature Converter ===
0°C → Fahrenheit: 32.00°F
100°C → Fahrenheit: 212.00°F
98.6°F → Celsius: 37.00°C
300K → Celsius: 26.85°C

Using master converter:
convertTemp(25, "C", "F") → 77.00
convertTemp(98.6, "F", "C") → 37.00
convertTemp(0, "C", "K") → 273.15
convertTemp(300, "K", "C") → 26.85

Self-Check Questions:

  • What happens if you call convertTemp(25) with no fromUnit or toUnit?
  • Which syntax did you use for each function · declaration, expression, or arrow?
  • How would you add Rankine as a new unit?

🏋️ Exercise 2 · Flexible Statistics Calculator

Objective: Practice rest parameters, the arguments object, and returning objects.

Real-world Scenario: A data analytics dashboard needs to compute statistics for any number of data points a user selects.

Warm-up Mini-Example:

javascript
function average(...nums) {
  return nums.reduce((sum, n) => sum + n, 0) / nums.length;
}
console.log(average(10, 20, 30));  // 20
console.log(average(5, 15));       // 10

Your Exercise:

Build a stats(...numbers) function using rest parameters that:

  1. Counts how many numbers were passed
  2. Finds the minimum value
  3. Finds the maximum value
  4. Calculates the sum
  5. Calculates the mean (average)
  6. Calculates the range (max - min)
  7. Returns ALL results as a single object

Expected Output:

javascript
let result = stats(85, 72, 91, 60, 88, 74, 95, 68);
console.log(result);

// Expected:
{
  count: 8,
  min: 60,
  max: 95,
  sum: 633,
  mean: 79.13,
  range: 35
}

What-if Challenge: What should the function return if called with NO arguments? Handle this edge case gracefully.


🏋️ Exercise 3 · Arrow Function Array Processor

Objective: Practice arrow functions with array higher-order methods.

Real-world Scenario: An HR system processes employee records · filtering, transforming, and summarizing data.

Warm-up Mini-Example:

javascript
let employees = [
  { name: "Alice", dept: "Engineering", salary: 85000 },
  { name: "Bob",   dept: "Marketing",   salary: 60000 }
];

// Get names only:
let names = employees.map(e => e.name);
console.log(names);  // ["Alice", "Bob"]

Your Exercise:

javascript
let employees = [
  { name: "Alice Okafor",   dept: "Engineering", salary: 85000, years: 5 },
  { name: "Bob Mensah",     dept: "Marketing",   salary: 60000, years: 2 },
  { name: "Chioma Eze",     dept: "Engineering", salary: 95000, years: 8 },
  { name: "David Traoré",   dept: "HR",          salary: 55000, years: 3 },
  { name: "Emeka Obi",      dept: "Engineering", salary: 72000, years: 4 },
  { name: "Fatima Diallo",  dept: "Marketing",   salary: 68000, years: 6 },
];

Using ONLY arrow functions, write these operations:

  1. Get names of all Engineering employees
  2. Calculate a 10% raise for everyone and return new salary list
  3. Find all employees earning above ₦70,000
  4. Get the average salary across all employees
  5. Sort employees from highest to lowest salary
  6. Create a summary string for each: "Alice Okafor (5 yrs) · ₦85,000"

Expected Output:

code
Engineering employees: Alice Okafor, Chioma Eze, Emeka Obi

After 10% raise:
  Alice Okafor:  ₦93,500
  Bob Mensah:    ₦66,000
  ...

Earning above ₦70k: Alice Okafor, Chioma Eze, Fatima Diallo, Emeka Obi

Average salary: ₦72,500.00

Sorted (highest to lowest):
  1. Chioma Eze    — ₦95,000
  2. Alice Okafor  — ₦85,000
  3. Emeka Obi     — ₦72,000
  4. Fatima Diallo — ₦68,000
  5. Bob Mensah    — ₦60,000
  6. David Traoré  — ₦55,000

✏️ Your Task
Practise what you just learned about 18. Applied Exercises. Open your editor, type the examples above by hand, modify them, and observe what changes.
🏗️ Build It — Mini Project
🏫 Project Overview

🏫 Project Overview

You will build a School Grade Management System using all function types covered in this tutorial. The system handles student registration, grade calculation, subject statistics, and report generation.

What you'll practice: Function declarations, expressions, arrow functions, default parameters, rest parameters, return values, IIFE for initialization, callbacks, and higher-order functions.


Stage 1 · Core Utility Functions (Setup)

Illustrative Preview:

starter.html
// A reusable grade calculator arrow function:
const getLetterGrade = score => {
  if (score >= 90) return "A";
  if (score >= 75) return "B";
  if (score >= 60) return "C";
  if (score >= 45) return "D";
  return "F";
};
console.log(getLetterGrade(87));  // "B"

Lesson 09 complete! 🎉

You covered: