TL;DR
Learn how to create reusable code with functions
Key concepts
- JavaScript functions
- JS function tutorial
- function declaration vs expression
- arrow functions JavaScript
Functions in JavaScript
Functions are the building blocks of JavaScript programs. They let you write code once and reuse it many times. Think of functions as recipes - you write the instructions once, and then you can follow them whenever you need.
What You'll Learn
By the end of this lesson you will finish three working functions under check: one written as a declaration that returns a computed value, one written as an arrow function doing the same job in a different shape, and one that uses a default parameter so it still works when an argument is left out.
You arrive able to store values in variables and say what type each one is (02-variables-and-types); you leave able to package a piece of work under a name, hand it inputs, and get a value back.
This lesson feeds the capstone's task-model milestone. It is not marked required for the final project — you could reach the Task Manager without it — but you would be rebuilding it there. The capstone's Task in 15-capstone-project is exactly this: functions that take a title, check it, and hand back a value. The milestone at the end of this lesson is where you confirm you have the pieces.
Basic Function Syntax
Here's how to create a simple function:
// Function declaration
function greet() {
console.log("Hello, World!");
}
// Calling the function
greet();
greet(); // You can call it multiple times
Functions with Parameters
Functions become more useful when they can work with different inputs:
// Function with one parameter
function greetPerson(name) {
console.log("Hello, " + name + "!");
}
greetPerson("Alice");
greetPerson("Bob");
greetPerson("Charlie");
// Function with multiple parameters
function introduce(name, age) {
console.log("My name is " + name + " and I am " + age + " years old.");
}
introduce("Alice", 25);
introduce("Bob", 30);
Return Values
Functions can send data back using the return keyword:
// Function that returns a value
function add(a, b) {
return a + b;
}
// Store the result in a variable
let sum = add(5, 3);
console.log("5 + 3 =", sum);
// Use the result directly
console.log("10 + 20 =", add(10, 20));
// Function with multiple calculations
function calculate(x, y) {
let sum = x + y;
let product = x * y;
return product; // Only the product is returned
}
console.log("Result:", calculate(4, 5));
Read the code sample, choose the output you expect, then submit.
JavaScript function with no return statement
Predict
Predict the output. The function computes a product but never uses return. What does the last line log?
function calculate(x, y) {
const product = x * y;
}
const result = calculate(4, 5);
console.log("Result:", result);Function Expressions
You can also create functions and assign them to variables:
// Function expression
const multiply = function(a, b) {
return a * b;
};
console.log("3 * 4 =", multiply(3, 4));
console.log("5 * 6 =", multiply(5, 6));
Choose one type name, then submit your answer.
Recall
Reaching back to 02-variables-and-types, no scrolling: that lesson had you run typeof over five values and flagged one surprising result. A function with no return hands back undefined. Which of these does typeof report for it?
Arrow Functions
Modern JavaScript has a shorter syntax for functions called arrow functions:
// Traditional function
function square(x) {
return x * x;
}
// Arrow function (shorter syntax)
const squareArrow = (x) => {
return x * x;
};
// Even shorter (one parameter, one expression)
const squareShort = x => x * x;
console.log("Square of 5:", square(5));
console.log("Square of 6:", squareArrow(6));
console.log("Square of 7:", squareShort(7));
// Arrow function with multiple parameters
const add = (a, b) => a + b;
console.log("10 + 15 =", add(10, 15));
Practical Examples
Let's create some useful functions:
// Convert Celsius to Fahrenheit
function celsiusToFahrenheit(celsius) {
return (celsius * 9/5) + 32;
}
console.log("0°C =", celsiusToFahrenheit(0), "°F");
console.log("25°C =", celsiusToFahrenheit(25), "°F");
console.log("100°C =", celsiusToFahrenheit(100), "°F");
// Check if a number is even
function isEven(number) {
return number % 2 === 0;
}
console.log("Is 4 even?", isEven(4));
console.log("Is 7 even?", isEven(7));
// Calculate the area of a rectangle
const calculateArea = (width, height) => width * height;
console.log("Area of 5x3 rectangle:", calculateArea(5, 3));
console.log("Area of 10x8 rectangle:", calculateArea(10, 8));
Ordering a Function Body
Inside a function body, order is not a matter of taste. Reassemble this one.
Arrange the code
Reassemble the body of describeTask(minutes, tag = 'task'), which converts a duration in minutes into a one-line description like 'docs takes 3 half-hours'. Every line uses a name the line above it introduces. Find the only arrangement that runs — then answer the real question: why must they run in this order and no other?
return label;const halves = hours * 2;const hours = minutes / 60;const label = tag + " takes " + halves + " half-hours";
Why that order? Build the value, then hand it back. return is the exit from the function — anything written below it is unreachable, which is why it always comes last in a straight-line body like this one.
Default Parameters
You can provide default values for parameters:
// Function with default parameter
function greetWithDefault(name = "Guest") {
console.log("Hello, " + name + "!");
}
greetWithDefault("Alice"); // Uses "Alice"
greetWithDefault(); // Uses default "Guest"
// Multiple default parameters
function createProfile(name = "Anonymous", age = 18) {
console.log(name + " is " + age + " years old");
}
createProfile("Bob", 25);
createProfile("Charlie");
createProfile();
Repairing a Missing Return
The QuickBite above asked you to predict what a function with no return gives back. Here it is as a bug to repair — in a program that runs cleanly and prints nonsense.
Debug
This should print the total for each order: the price times the quantity, plus a flat 3 for shipping. It runs without any error and prints 'Order 1 total: undefined' twice. Form a hypothesis about WHY before you change anything: what does totalFor compute, and what does it hand back?
// Work out the total cost of each order: the price times the quantity, plus a flat 3 for shipping.
function totalFor(price, quantity) {
const goods = price * quantity;
const total = goods + 3;
}
console.log("Order 1 total:", totalFor(10, 2));
console.log("Order 2 total:", totalFor(4, 5));Expected output:
Order 1 total: 23 Order 2 total: 23
Try It Yourself
Reading about functions is not the same as writing them. This is a build task: a small program that reports its own pass/fail. You are given fixed rectangle data and three empty functions to finish — a declaration, an arrow function, and one with a default parameter. Run it and it fails immediately, telling you which function is still missing. Implement each one until every check passes and it prints All checks passed.
The three functions reuse exactly what this lesson taught: writing a declaration and an arrow function, taking parameters, returning a value with return, and giving a parameter a default. The starter already has the data, the stubs, and the checks — you write only the logic inside each function. Nothing above spells out all three answers, so you will have to assemble them yourself.
Build
Finish the build. Three functions are stubbed out and the checks below them fail until each one returns the right value. Run it as-is to see which check fails first, decide what that function is missing, then implement the three functions until it prints 'All checks passed.' The checks run top to bottom, so the first failure you see is TODO 1 — implement it first, then work down.
const assert = require('assert');
// The data: rectangle dimensions to measure. Do NOT change this array.
const rectangles = [
{ label: "small", width: 5, height: 3 },
{ label: "wide", width: 10, height: 4 },
{ label: "square", width: 6, height: 6 },
];
// TODO 1: return the area of a rectangle (width times height).
// area(5, 3) -> 15
function area(width, height) {
// your code here
}
// TODO 2: return the perimeter of a rectangle: 2 * (width + height).
// perimeter(5, 3) -> 16
const perimeter = (width, height) => {
// your code here
};
// TODO 3: return a label like "small: 15" — the tag, a colon, a space, then the value.
// Give tag a default of "shape", so describe(15) uses "shape".
// describe(15, "small") -> "small: 15"
// describe(15) -> "shape: 15"
function describe(value, tag = "shape") {
// your code here
}
// --- Build checks: these must all pass. Do not edit below this line. ---
assert.strictEqual(
area(5, 3),
15,
"area(width, height) should return width times height",
);
assert.strictEqual(
perimeter(5, 3),
16,
"perimeter(width, height) should return 2 * (width + height)",
);
assert.strictEqual(
describe(15),
"shape: 15",
"describe(value) should default its tag to 'shape' when no tag is passed",
);
assert.strictEqual(
describe(15, "small"),
"small: 15",
"describe(value, tag) should join the tag and value as 'tag: value'",
);
console.log("All checks passed.");
console.log("Area 5x3:", area(5, 3));
console.log("Perimeter 5x3:", perimeter(5, 3));
console.log("Described:", describe(area(rectangles[0].width, rectangles[0].height), rectangles[0].label));Expected output:
All checks passed. Area 5x3: 15 Perimeter 5x3: 16 Described: small: 15
Once it passes, try two variations and predict each before running:
- Drop the default. Rewrite
describe's signature asfunction describe(value, tag)— notag = "shape"default. Predict whatdescribe(15)returns with no second argument before running it. An omitted parameter isundefined, so the string becomes"undefined: 15"and the default-tag check fails — the exact reason the default parameter was there. - The arrow that forgets to return. Give
perimetera block body with noreturn:(width, height) => { 2 * (width + height); }. Decide whatperimeter(5, 3)yields before running. A{ }arrow body does not return its last expression the way a concise=> 2 * (width + height)body does, so the function returnsundefinedand the perimeter check fails.
Milestone — the Task Model
This is the first of the capstone's four milestones, and it is a checkpoint rather than a build. The Task Manager's Task in 15-capstone-project is a function that takes a title and an optional id, rejects a title that is empty or too long, fills in a status and a timestamp, and hands the finished task back. Every one of those verbs is something you did in this lesson: take parameters, apply a default when an argument is missing, compute, and return.
What the increment buys you is that the capstone's Step 1 will read as ordinary code rather than new syntax — the only genuinely new idea there is attaching methods to the model, which arrives in 06-objects-and-prototypes. Confirm the four capabilities below and that step is already within reach.
Review each checklist item, then mark the milestone complete when all are true.
Capstone milestone
Milestone — the Task model. Confirm the four function skills the capstone's Task leans on, before 15-capstone-project asks you to write it. Task itself also needs one thing you have not met yet: attaching data to an object with new, which arrives in 06-objects-and-prototypes.
Hint: This checkpoint confirms the underlying skills; it does not ask you to build the full capstone yet.
- Can write a function that takes a task's details as parameters and returns a value built from them
- Can read a helper written either as a declaration or as an arrow function, since the capstone uses both
- Can give a parameter a default value, so a function still works when that argument is left out
- Can spot a helper that computes the right value and forgets to return it — the bug that makes a capstone step yield undefined
Taking It Somewhere New
Transfer
You have written functions whose signature carries real information: how many parameters there are, and which ones have a default so they may be omitted. New setting: TypeScript, which is JavaScript plus written-down types, where the same function gains an annotation on each parameter — the commented-out line in the code below shows it. Which part of the behaviour is genuinely new, and which part is the JavaScript you already wrote?
// JavaScript — the signature already says what may be omitted.
const describe = (value, tag = "shape") => tag + ": " + value;
console.log(describe(15, "small"));
console.log(describe(15));
// TypeScript — the same function with types written down.
// const describe = (value: number, tag: string = "shape") => tag + ": " + value;Key Takeaways
- Functions help organize and reuse code
- Functions can accept parameters (inputs) and return values (outputs)
- There are multiple ways to create functions: declarations, expressions, and arrow functions
- Arrow functions (
=>) provide a shorter syntax for simple functions - Default parameters make functions more flexible
Next Steps
Now that you know how to create functions, you're ready to learn about control flow - how to make decisions and repeat actions in your code using if statements and loops!
Pro Tip: When writing functions, give them clear, descriptive names that explain what they do. A function called
calculateTotalis much better than one calledcalcorx. Good names make your code easier to read and understand!
Two-tier handoff: this document is the complete reading surface. Continue learning for stateful practice, progress, and real sandbox execution.