JavaScript Function Declarations Get Certified
A function is a reusable block of code designed to perform a specific task. Instead of repeating the same code multiple times, you can define it once as a function and call it whenever needed.
A function declaration (also called a function statement) is one of the most common ways to define a function in JavaScript.
In this lesson, you will learn how to declare a function, pass it parameters, return values from it, and understand a key behavior called hoisting.
Basic Function Declaration Syntax
A function declaration starts with the function
keyword, followed by a name, a list of parameters in parentheses,
and a body wrapped in curly braces.
What this code does: A function declaration defines a reusable block of code with the function keyword.
Calling greet() runs the body and prints the greeting. Nothing runs until the function is called.
function greet() {
console.log("Hello, Michael!");
}
greet();
function greet() { is a function declaration. The function keyword tells JavaScript you are defining a function, greet is its name, and the empty parentheses () mean it takes no parameters. The opening brace { starts the function body. At this point the code inside is only stored; nothing is printed yet.console.log("Hello, Michael!"); is the code inside the function. It runs every time the function is called, and prints Hello, Michael! to the console. It is indented to show that it belongs to the function.} ends the function body. Defining the function is now complete, but it has not run yet.greet(); calls the function: the name followed by parentheses. JavaScript jumps into the function, runs its body and then comes back. This call is what produces the output Hello, Michael!. Without this line, nothing would be printed.Defining a function does not run its code. The function only runs when it is called, using its name followed by parentheses.
Function Parameters
Parameters let you pass values into a function so it can use them while it runs. The values you provide when calling the function are called arguments.
What this code does: Parameters let you pass different values into the same function.
name receives “Michael” on the first call and “Emily” on the second, producing two different greetings.
function greet(name) {
console.log("Hello, " + name + "!");
}
greet("Michael");
greet("Emily");
function greet(name) { declares a function with one parameter, name. A parameter is a placeholder variable that exists inside the function and receives its value each time the function is called.console.log("Hello, " + name + "!"); joins three pieces of text with the + operator: "Hello, ", the value of name and "!". The result depends on what was passed in.} ends the function body.greet("Michael"); calls the function and passes the argument "Michael". Inside the function, name becomes "Michael", so the output is Hello, Michael!.greet("Emily"); calls the same function again, but now name is "Emily". The output is Hello, Emily!. One function, written once, gives different results for different arguments.A function can accept multiple parameters, separated by commas.
What this code does: Multiple parameters are separated by commas.
addNumbers(5, 10) adds the two arguments and logs the sum. The function itself does not return a value.
function addNumbers(a, b) {
console.log(a + b);
}
addNumbers(5, 10);
function addNumbers(a, b) { declares a function with two parameters, a and b, separated by a comma. They receive the arguments in the order they are passed: the first argument goes to a and the second to b.console.log(a + b); adds the two numbers and prints the sum. Since both are numbers, + performs addition. Note that this function only prints the sum; it does not give it back to the caller.} ends the function body.addNumbers(5, 10); passes 5 to a and 10 to b. The function adds them and prints 15.The return Statement
Instead of just printing a value, a function can send a value
back to the code that called it using return.
What this code does: return sends a value back to the caller so it can be stored or reused.
The sum is returned, stored in result, and then printed.
function addNumbers(a, b) {
return a + b;
}
let result = addNumbers(5, 10);
console.log(result);
function addNumbers(a, b) { declares a function with two parameters, a and b.return a + b; calculates the sum and sends it back to the code that called the function. The return statement also ends the function immediately. Unlike console.log, which only displays a value, return gives the value back so it can be stored or used.} ends the function body.let result = addNumbers(5, 10); calls the function with 5 and 10. The function returns 15, and that value is stored in the variable result. Nothing is printed by this line.console.log(result); prints the value held in result. The output is 15.
A return statement immediately exits the function,
so any code written after it inside the same block never runs.
What this code does: A function can return different values based on conditions. Ages 20 and 15 produce “Adult” and “Minor” respectively via early returns.
function checkAge(age) {
if (age >= 18) {
return "Adult";
}
return "Minor";
}
console.log(checkAge(20));
console.log(checkAge(15));
function checkAge(age) { declares a function with one parameter, age.if (age >= 18) { checks whether the age is 18 or more. For 20 this is true; for 15 it is false.return "Adult"; runs only when the condition is true. It sends back the text "Adult" and immediately exits the function, so nothing after it in the function runs.} closes the if block that began on line 2.return "Minor"; is reached only when the if condition was false, because the earlier return would already have ended the function. So there is no need for an else. It returns "Minor".} ends the function body.checkAge(20) returns "Adult" (since 20 is at least 18), and console.log prints it: Adult.checkAge(15) skips the if block and returns "Minor", which is printed: Minor.Functions Without a return Statement
If a function doesn’t include a return statement, it
automatically returns undefined.
What this code does: Without a return, a function returns undefined.
logMessage only prints; assigning its result to result gives undefined.
function logMessage(message) {
console.log(message);
}
let result = logMessage("Hello!");
console.log(result);
function logMessage(message) { declares a function with one parameter, message.console.log(message); prints the value of the parameter. The function has no return statement, so it does its job (printing) but gives nothing back.} ends the function body. A function that reaches its end without a return automatically returns undefined.let result = logMessage("Hello!"); calls the function. While it runs, it prints Hello!. When it finishes, it returns undefined, and that value is stored in result.console.log(result); prints what was stored, which is undefined. The complete output is Hello! followed by undefined.Default Parameters
You can give a parameter a default value, which is used
automatically if no argument (or undefined) is
passed for that parameter.
What this code does: Default parameters provide a fallback when an argument is omitted. The first call uses “Michael”; the second uses the default “Guest”.
function greet(name = "Guest") {
console.log("Hello, " + name + "!");
}
greet("Michael");
greet();
function greet(name = "Guest") { declares a parameter with a default value. The = "Guest" part means: if no argument is passed for name (or undefined is passed), use "Guest" instead.console.log("Hello, " + name + "!"); builds and prints the greeting using whatever value name has on this call.} ends the function body.greet("Michael"); passes an argument, so the default is ignored and name is "Michael". The output is Hello, Michael!.greet(); passes nothing, so name falls back to its default, "Guest". The output is Hello, Guest!.Missing or Extra Arguments
JavaScript does not require the number of arguments to match the
number of parameters. Missing arguments become
undefined, and extra arguments are simply ignored
(unless you use the arguments object or rest
parameters to access them).
What this code does: JavaScript does not enforce argument count. Missing arguments are undefined;
extra arguments are ignored. One call gets undefined for b; the other ignores the third value.
function addNumbers(a, b) {
console.log(a, b);
return a + b;
}
console.log(addNumbers(5));
console.log(addNumbers(5, 10, 20));
function addNumbers(a, b) { declares a function that expects two arguments.console.log(a, b); prints both parameters on one line, separated by a space, so you can see exactly what the function received on each call.return a + b; returns the result of adding the parameters.} ends the function body.addNumbers(5) passes only one argument. a becomes 5 and b gets no value, so it is undefined. JavaScript does not raise an error. Inside the function, line 2 prints 5 undefined. Then 5 + undefined is NaN (not a number), which is returned and printed by the outer console.log.addNumbers(5, 10, 20) passes three arguments. a is 5, b is 10, and the third value 20 is simply ignored because there is no parameter for it. Line 2 prints 5 10, and the function returns 15, which is printed. The four lines of output are 5 undefined, NaN, 5 10 and 15.
Since b is undefined in the first call,
a + b results in NaN.
Function Declarations Are Hoisted
Function declarations are fully hoisted, meaning you can call the function before it appears in the code, and it will still work correctly.
What this code does: Function declarations are hoisted—you can call them before they appear in the code.
square(5) works even though the function is defined later in the file.
console.log(square(5));
function square(number) {
return number * number;
}
console.log(square(5)); calls square on the very first line, before the function is defined below. In many languages this would be an error. In JavaScript it works, because of hoisting: before running any code, JavaScript scans the scope and moves function declarations to the top, so square already exists. The output is 25.function square(number) { declares the function with one parameter, number. Even though it appears after the call, the whole declaration (name and body) was made available at the start.return number * number; multiplies the parameter by itself and returns the result. For 5, this gives 25.} ends the function body. Remember that this hoisting applies to function declarations only, not to function expressions or arrow functions.This works because JavaScript moves the entire function declaration (name and body) to the top of its scope before the code runs. This behavior is unique to function declarations — function expressions and arrow functions are not hoisted the same way.
Naming Functions
Function names follow the same rules as variable names: they can
contain letters, numbers, underscores, and dollar signs, but
cannot start with a number. Function names are typically written
in camelCase and describe what the function does.
What this code does: A practical function that multiplies price by quantity and returns the total. Clear names make the purpose obvious without reading the body.
function calculateTotalPrice(price, quantity) {
return price * quantity;
}
console.log(calculateTotalPrice(20, 3));
function calculateTotalPrice(price, quantity) { declares a function with two parameters. The name is written in camelCase (first word lowercase, each following word capitalized) and says exactly what the function does. The parameter names, price and quantity, are equally clear.return price * quantity; multiplies the price by the quantity with the * operator and returns the result.} ends the function body.calculateTotalPrice(20, 3) passes 20 as the price and 3 as the quantity. The function returns 60, and console.log prints it: 60. Notice that you can understand this line without reading the function body, which is the point of good naming.Calling a Function Multiple Times
One of the main benefits of functions is reusability. Once defined, a function can be called as many times as needed with different arguments.
What this code does: The same function can be called many times with different arguments. Each call returns a new result; the function body is written once and reused.
function square(number) {
return number * number;
}
console.log(square(2));
console.log(square(5));
console.log(square(10));
function square(number) { declares a function with one parameter, number. It is written once, but can be called as many times as you need.return number * number; multiplies the number by itself and returns the result.} ends the function body.square(2) returns 2 * 2, which is 4. console.log prints 4.square(5) reuses the same function with a different argument and returns 25.square(10) returns 100. The output of the three calls is 4, 25 and 100, without repeating the multiplication logic.Practical Example
Let’s declare a function that calculates the final price of an item after applying a discount.
What this code does: Combining parameters, a default, and return.
A 25% discount reduces 200 to 150; omitting the discount leaves the price unchanged.
function applyDiscount(price, discountPercent = 0) {
const multiplier = 1 - (discountPercent / 100);
return price * multiplier;
}
console.log(applyDiscount(200, 25));
console.log(applyDiscount(150));
function applyDiscount(price, discountPercent = 0) { declares two parameters. price is required, and discountPercent has a default of 0, so a call that leaves out the discount means no discount.const multiplier = 1 - (discountPercent / 100); converts the percentage into the fraction of the price that is still paid. For a 25% discount: 25 / 100 is 0.25, and 1 - 0.25 is 0.75. With the default of 0, the multiplier is 1. It is a const because it never changes inside the function.return price * multiplier; multiplies the price by the multiplier and returns the discounted price.} ends the function body.applyDiscount(200, 25): the multiplier is 0.75, so the function returns 200 * 0.75, which is 150. The output is 150.applyDiscount(150) omits the second argument, so discountPercent is 0, the multiplier is 1, and the price stays 150. The output is 150.Common Mistakes With Function Declarations
- Forgetting to call the function, and expecting the code inside it to run automatically.
- Confusing parameters (the names in the function definition) with arguments (the actual values passed in).
- Forgetting
return, and expecting a value even though the function only logs something to the console. - Assuming code after a
returnstatement in the same block still runs. - Declaring two functions with the same name, where the second declaration silently overwrites the first.
Best Practices for Function Declarations
- Give functions clear, descriptive names that explain what they do, such as
calculateTotalinstead ofdoStuff. - Keep each function focused on doing one specific task.
- Use default parameters instead of manually checking for
undefinedinside the function body. - Avoid relying on hoisting for readability — define important functions near the top of your file when practical.
- Prefer returning values over logging directly inside a function, so the function’s result can be reused elsewhere.
Quick Summary
- A function declaration starts with the
functionkeyword, followed by a name, parameters, and a body. - Parameters are placeholders; arguments are the actual values passed when calling the function.
returnsends a value back and immediately exits the function.- A function without
returnreturnsundefinedby default. - Parameters can have default values used when no argument is provided.
- Function declarations are hoisted, so they can be called before they appear in the code.
Try It Yourself
Modify the function below. Try adding a new parameter, changing the default value, or calling the function with different arguments.
What this code does: Practice example: change the default age or the returned string, then click Test My Code to see how parameters and defaults work together.
function introduce(name, age = 18) {
return name + " is " + age + " years old.";
}
console.log(introduce("Michael", 28));
console.log(introduce("Alex"));
function introduce(name, age = 18) { declares two parameters. name is required, while age has a default of 18. This is the line to experiment with: change the default, or add a third parameter such as city.return name + " is " + age + " years old."; joins the pieces of text and the values with + and returns the finished sentence. The function returns the text instead of printing it, so the caller decides what to do with it.} ends the function body.introduce("Michael", 28) passes both values, so the default is not used. The returned sentence is printed: Michael is 28 years old.introduce("Alex") passes only the name, so age uses its default of 18. The output is Alex is 18 years old.Tip: A good function name should let someone understand what it does without needing to read its code. If you’re struggling to name a function clearly, it might be doing too many things at once.
Understanding function declarations is essential before moving on to function expressions, arrow functions, scope, and more advanced JavaScript concepts.
🧪 Test Your JavaScript Code
Edit the code on the left and click “Run Code” to see the console output on the right.
Click “Run Code” to see the output here.
Code Explanation
The complete example stays visible. Use Previous and Next to move through its logical blocks.
Select Next to begin exploring the code.