Historical Context & Motivation
Before functions existed in programming, developers wrote code as long, linear scripts. If you needed the same calculation in three different places, you literally copied and pasted the same lines three times. This made programs enormous, error-prone, and painful to update. The idea of packaging instructions into a named, reusable block—a function—solved this problem and changed the course of software development.
So how exactly do you create and use functions in JavaScript? And why does the language give you two different syntaxes—declarations and expressions—for essentially the same idea? Understanding both forms, and the subtle differences between them, is essential for writing clean, organized JavaScript code.
Core Principles & Definitions
A function is a self-contained block of code designed to perform a specific task. You define it once and then call (invoke) it whenever you need that task performed. Functions accept input through parameters, process that input, and can send back output using a return statement. JavaScript provides two primary ways to create functions: function declarations and function expressions.
Function Declaration
function keyword followed by a name. It is hoisted, meaning JavaScript moves it to the top of its scope, so you can call it before the line where it appears in your code.Function Expression
const or let. It is not hoisted, so it can only be called after the line where it is defined.Parameters vs. Arguments
Return Values
return keyword sends a value back to wherever the function was called. If no return statement exists, the function returns undefined by default.Hoisting
const or let are not.Visual Explanation — Anatomy of a Function
function keyword, followed by the name, parameters in parentheses, and the body in curly braces. Bottom: A function expression assigns an anonymous function to a variable. Notice the trailing semicolon, since the entire line is a variable assignment statement.The diagram above highlights the structural similarities and differences between the two forms. Both have a set of parameters in parentheses, a function body enclosed in curly braces, and a return statement. The key visual difference is that a declaration starts with function as the very first word, while an expression begins with a variable keyword like const and uses the assignment operator = before the function keyword.
How It Works — Hoisting and Execution Flow
When JavaScript loads your script, it doesn't simply run code line by line. Instead, the engine performs a two-pass process. During the first pass (the creation phase), JavaScript scans the entire scope for function declarations and variable declarations. Function declarations are fully hoisted—both the name and the function body are moved to the top of the scope in memory. Variable declarations using const or let are recognized but remain in a temporal dead zone until the engine reaches the line where they are assigned.
Declaration: Hoisted and Available Everywhere
Because function declarations are fully hoisted, you can call them before they appear in your source code. For example, the following code works perfectly:
const result = greet("Alice");
console.log(result); // "Hello, Alice!"
function greet(name) {
return "Hello, " + name + "!";
}Expression: Must Be Defined First
If you try the same pattern with a function expression, JavaScript throws a ReferenceError because the variable hasn't been initialized yet at the point of the call. You must define the expression before you call it.
// const result = greet("Alice"); // ❌ ReferenceError!
const greet = function(name) {
return "Hello, " + name + "!";
};
const result = greet("Alice"); // ✓ Works fine hereCalling a Function
Regardless of whether you used a declaration or expression, you call (invoke) a function the same way: write the function name followed by parentheses containing the arguments. The parentheses are what actually execute the function. Without them, you're just referencing the function object itself—not running it. For example, greet is the function object, while greet("Alice") executes the function with the argument "Alice".
Detailed Comparison — Declarations vs. Expressions
| Feature | Function Declaration | Function Expression |
|---|---|---|
| Syntax starts with | function name() {} | const name = function() {}; |
| Hoisted? | Yes — fully hoisted | No — must be defined first |
| Has a name? | Always named | Can be anonymous or named |
| Used as a value? | Not typically | Yes — can be passed as argument, stored in array, etc. |
| Trailing semicolon? | No | Yes — it's a variable assignment |
| Best for | Top-level utility functions you want available everywhere | Callbacks, closures, and controlled scoping |
In practice, both forms create functions that behave identically once defined. The choice between them often comes down to style and context. Many JavaScript teams prefer const-based expressions because they enforce clear top-to-bottom ordering, while others prefer declarations for the readability of having function names stand out at the start of each line.
Worked Example — Building a Tip Calculator
Let's build a small tip calculator using both a function declaration and a function expression. We'll write a function that takes a bill amount and a tip percentage, then returns the total amount to pay.
function keyword, give it a descriptive name, and list two parameters: bill (the subtotal) and tipPercent (the desired tip as a whole number like 20 for 20%).
function calculateTotal(bill, tipPercent) {
const tip = bill * (tipPercent / 100);
return bill + tip;
}const total = calculateTotal(50, 20);tip = 50 × (20 / 100) = 10. Return value: 50 + 10 = 60total. We can now log it or use it elsewhere.
console.log(total); // 60const.
const calculateTotal = function(bill, tipPercent) {
const tip = bill * (tipPercent / 100);
return bill + tip;
};
Calling it works the same way: calculateTotal(85, 15) returns 97.75.calculateTotal, getUserName, formatDate. This makes your code read almost like English and helps other developers (and future you) understand what each function does.Strengths, Limitations & When to Use Each
| Criterion | Declaration Wins | Expression Wins |
|---|---|---|
| Readability | Stands out clearly; name comes right after the keyword | Groups nicely when assigned alongside other variables |
| Flexibility | Less flexible—always creates a named function in the current scope | Can be anonymous, passed as a callback, or assigned conditionally |
| Order independence | Call it anywhere in its scope thanks to hoisting | Must define before calling—forces logical ordering |
| Debugging | Always shows name in stack traces | Anonymous expressions show as "anonymous" unless named |
| Reassignment safety | Can accidentally be overwritten if another declaration uses the same name | Using const prevents accidental reassignment |
Connection to Arrow Functions & Advanced Patterns
Once you're comfortable with declarations and expressions, you'll encounter arrow functions—a shorthand syntax introduced in ES6 (2015). Arrow functions are a type of function expression written with the => symbol. They're especially popular for short, one-line operations and callbacks.
| Style | Syntax Example | Notes |
|---|---|---|
| Declaration | function add(a, b) { return a + b; } | Hoisted; always named |
| Expression | const add = function(a, b) { return a + b; }; | Not hoisted; can be anonymous |
| Arrow (ES6) | const add = (a, b) => a + b; | Shortest form; implicit return for single expressions; different this behavior |
| IIFE | (function() { /* runs immediately */ })(); | Immediately Invoked Function Expression; creates private scope |
You'll also encounter functions used as callbacks (functions passed as arguments to other functions), closures (functions that remember variables from their outer scope), and higher-order functions (functions that accept other functions as parameters or return them). All of these powerful patterns build directly on the function declaration and expression foundations you've learned in this lesson.
this keyword). Master traditional declarations and expressions first—they're the foundation everything else builds on.Practice Problems
function multiply(x, y) { return x * y; } followed by multiply(3, 7), identify which are parameters and which are arguments.celsiusToFahrenheit that takes a temperature in Celsius and returns it converted to Fahrenheit using the formula F = C × 9/5 + 32. Then call it with the value 25 and state the result.console.log(square(4));
const square = function(n) {
return n * n;
};const variable called getLetterGrade that takes a numeric score (0–100) and returns the letter grade: 90–100 = "A", 80–89 = "B", 70–79 = "C", 60–69 = "D", below 60 = "F". Show the function and demonstrate calling it with a score of 84.const function expressions because they enforce clear ordering. Write a short paragraph presenting at least one advantage and one disadvantage of each approach, and describe a specific scenario where each form is the better choice.Lesson Summary
JavaScript provides two primary ways to create functions. A function declaration begins with the function keyword followed by a name, is hoisted to the top of its scope, and can be called before the line where it appears in your code. A function expression assigns a function (often anonymous) to a variable using const or let, is not hoisted, and must be defined before it is called. Both forms accept parameters (placeholder names) and receive arguments (actual values) when invoked.
You call any function by writing its name followed by parentheses: myFunction(arg1, arg2). The return keyword sends a value back to the caller; without it, the function returns undefined. Use declarations for top-level utility functions and expressions for callbacks, conditional assignments, and enforcing strict code ordering. Mastering both forms prepares you for arrow functions, closures, and higher-order functions—the advanced patterns that make JavaScript so powerful.