Lesson 4: Functions
Why functions exist, how to define and call them, parameter handling, returns, scope, and common patterns for clear, reusable code.
Learning goals
- Explain why functions are useful (reuse, abstraction, clarity).
- Know the difference between declarations, expressions, and arrow functions.
- Use parameters and return values correctly.
- Understand basic scope and guard clauses (early returns).
- Name functions clearly and avoid common mistakes.
Why functions exist
Functions let you group a sequence of steps and give it a name. This makes code reusable, easier to read, and easier to test. Instead of copying the same code, you call a function whenever needed.
Function anatomy
Key parts: name, parameters, body, and return value.
// function declaration
function greet(name) {
return 'Hello ' + name;
}
// function expression
const greet2 = function(name) {
return 'Hi ' + name;
};
// arrow function (shorter syntax)
const greet3 = (name) => `Hey ${name}`;
console.log(greet('Ava')); // 'Hello Ava'
Parameters vs arguments
Parameters are the names in the function definition. Arguments are the actual values you pass when calling the function.
function add(a, b) { // a, b are parameters
return a + b;
}
const result = add(2, 3); // 2 and 3 are arguments
Return value
Use return to send a value out of a function. If you omit return, the function returns undefined.
function noReturn() {
const x = 1 + 2;
}
console.log(noReturn()); // undefined
// concise return
function withReturn() { return 42; }
console.log(withReturn()); // 42
Scope basics
Variables declared inside a function are local to that function. They are not visible outside. This prevents accidental conflicts between different parts of code.
function example() {
const secret = 'shh'; // local
return secret;
}
// secret is not defined here
// console.log(secret); // ReferenceError
Guard clauses & early return
Use early returns to handle invalid input and keep the main logic less nested.
function divide(a, b) {
if (b === 0) return null; // guard clause
return a / b;
}
Naming functions clearly
Choose names that describe what the function does (verb + noun). E.g. formatDate, calculateTotal, isAdult.
Common mistakes
- Forgetting
returnwhen you need a value. - Using variables not defined in scope (ReferenceError).
- Confusing calling vs referencing:
fn()calls,fnreferences. - Mutating shared state inside functions — prefer pure functions when possible.
Examples
Double a number
function double(n) { return n * 2; }
console.log(double(4)); // 8
fullName from first & last
function fullName(first, last) {
return first + ' ' + last;
}
console.log(fullName('Ava', 'Smith')); // 'Ava Smith'
clamp(value, min, max)
function clamp(value, min, max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
console.log(clamp(5, 1, 4)); // 4
isAdult(age)
function isAdult(age) {
const n = Number(age);
if (Number.isNaN(n)) return false;
return n >= 18;
}
console.log(isAdult('20')); // true
Practice tasks
- Implement
double(n)— returns 2*n. - Implement
fullName(first, last)— returns combined name. - Implement
clamp(value,min,max)— keep value within bounds. - Implement
isAdult(age)— returns true for 18+ (handle strings).
Summary checklist
- Can define functions as declarations, expressions, and arrows.
- Know parameters vs arguments and how return works.
- Use guard clauses for early exits and avoid deep nesting.
- Keep variables scoped and name functions clearly.