JavaScript • Functions and Program Structure

Function Declarations & Expressions — Define and call functions (function declarations and expressions)

Learn to bundle reusable logic into functions—the building blocks of every JavaScript program.

JavaScript emblem with code brackets, braces, and a code file.
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

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.

1958 • LISP and First-Class Functions

John McCarthy created LISP, one of the first languages to treat functions as values that can be stored and passed around—an idea that deeply influenced JavaScript decades later.

1972 • C Language Standardizes Function Syntax

Dennis Ritchie's C language popularized the pattern of declaring functions with a name, a parameter list, and a body enclosed in curly braces—a style JavaScript would later adopt.

1995 • JavaScript Is Born

Brendan Eich created JavaScript in just 10 days at Netscape, blending C-style function declarations with LISP-style function expressions. Both forms have been core to the language ever since.

2015 • ES6 Adds Arrow Functions

ECMAScript 2015 introduced arrow functions (=>), giving developers an even shorter syntax for writing function expressions while preserving all the original forms.

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.

SECTION 2

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.

1

Function Declaration

Begins with the 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.
2

Function Expression

Assigns a function (often anonymous) to a variable using const or let. It is not hoisted, so it can only be called after the line where it is defined.
3

Parameters vs. Arguments

Parameters are placeholder names listed in the function definition. Arguments are the actual values you pass when calling the function.
4

Return Values

The return keyword sends a value back to wherever the function was called. If no return statement exists, the function returns undefined by default.
5

Hoisting

Hoisting is JavaScript's behavior of processing certain declarations before executing any code. Function declarations are fully hoisted; function expressions stored in const or let are not.
✦

KEY TAKEAWAY

Think of a function like a recipe card in a kitchen. The recipe name is the function's name, the ingredients list corresponds to the parameters, the cooking steps are the function body, and the finished dish is the return value. A function declaration is like a recipe pinned permanently to the wall—you can reference it from anywhere. A function expression is like writing the recipe on a sticky note and handing it to someone—they can only use it after they receive it.

SECTION 3

Visual Explanation — Anatomy of a Function

Anatomy of a Function DeclarationfunctioncalculateArea(width,height){const area = width * height;returnarea;}keywordfunction nameparametersfunction bodyreturn statementAnatomy of a Function ExpressionconstcalculateArea=function(width,height){const area = width * height;returnarea;};variable keywordvariable nameparametersNote the trailing semicolon — the whole statement is a variable assignment.No semicolon needed — this is a standalone declaration.
Top: A function declaration starts with the 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.

SECTION 4

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:

💡

Declaration — Hoisting in Action

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.

⚠

Expression — Order Matters

// const result = greet("Alice"); // ❌ ReferenceError! const greet = function(name) { return "Hello, " + name + "!"; }; const result = greet("Alice"); // ✓ Works fine here

Calling 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".

SECTION 5

Detailed Comparison — Declarations vs. Expressions

Hoisting Behavior — Declaration vs. ExpressionHow JavaScript processes your code before executing itFunction Declarationfunction add(a, b) { return a+b; }Creation PhaseMemory after hoisting:add → ƒ(a, b) { return a+b; }✓ Name AND body are fully available✓ Can be called from anywhere in scopeFunction Expressionconst add = function(a, b) { ... };Creation PhaseMemory after hoisting:add → ❌ TDZ (not initialized)✗ Variable recognized but empty✗ Calling before definition → ReferenceErrorExecution Phase (line by line)add(3, 5) → 8 ✓ anytimeadd(3, 5) → 8 ✓ after definitionBoth produce identical results once the function is properly defined.
This diagram compares what happens during JavaScript's creation phase for declarations (left, fully hoisted) versus expressions (right, in the temporal dead zone until defined). During the execution phase, both work identically once defined.
FeatureFunction DeclarationFunction Expression
Syntax starts withfunction name() {}const name = function() {};
Hoisted?Yes — fully hoistedNo — must be defined first
Has a name?Always namedCan be anonymous or named
Used as a value?Not typicallyYes — can be passed as argument, stored in array, etc.
Trailing semicolon?NoYes — it's a variable assignment
Best forTop-level utility functions you want available everywhereCallbacks, closures, and controlled scoping

Key differences between function declarations and function expressions

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.

SECTION 6

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.

Tip Calculator — Function Declaration

  1. 1

    Step 1 — Define the function

    We use the 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; }
  2. 2

    Step 2 — Call the function with arguments

    We invoke the function by writing its name followed by parentheses containing the actual values (arguments). const total = calculateTotal(50, 20);
    Inside the function: tip = 50 × (20 / 100) = 10. Return value: 50 + 10 = 60
  3. 3

    Step 3 — Use the returned value

    The returned value is stored in total. We can now log it or use it elsewhere. console.log(total); // 60
    Output: 60
  4. 4

    Step 4 — Rewrite as a function expression

    The exact same logic, but now stored in a variable using const. 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.
    tip = 85 × 0.15 = 12.75 → total = 97.75
💡

Pro Tip

Give your functions descriptive names that start with a verb: calculateTotal, getUserName, formatDate. This makes your code read almost like English and helps other developers (and future you) understand what each function does.

SECTION 7

Strengths, Limitations & When to Use Each

CriterionDeclaration WinsExpression Wins
ReadabilityStands out clearly; name comes right after the keywordGroups nicely when assigned alongside other variables
FlexibilityLess flexible—always creates a named function in the current scopeCan be anonymous, passed as a callback, or assigned conditionally
Order independenceCall it anywhere in its scope thanks to hoistingMust define before calling—forces logical ordering
DebuggingAlways shows name in stack tracesAnonymous expressions show as "anonymous" unless named
Reassignment safetyCan accidentally be overwritten if another declaration uses the same nameUsing const prevents accidental reassignment

When declarations or expressions have the advantage

⚖

CHOOSING THE RIGHT FORM

Think of function declarations like permanent tools hanging on a workshop wall—always available no matter where you stand in the room. Function expressions are like portable power tools stored in a toolbox—you need to unpack them before use, but they're easier to hand off to someone else. Use declarations for general utility functions that should be accessible everywhere, and expressions when you need to pass functions as values, use them in callbacks, or ensure strict top-to-bottom code flow.

SECTION 8

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.

StyleSyntax ExampleNotes
Declarationfunction add(a, b) { return a + b; }Hoisted; always named
Expressionconst 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

Evolution of function syntax in JavaScript

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.

ℹ

Looking Ahead

Arrow functions simplify syntax but have important behavioral differences (especially with the this keyword). Master traditional declarations and expressions first—they're the foundation everything else builds on.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain the difference between a parameter and an argument. In the code function multiply(x, y) { return x * y; } followed by multiply(3, 7), identify which are parameters and which are arguments.
Show answer
Parameters are the placeholder variable names listed in the function definition. In this case, x and y are parameters. Arguments are the actual values passed when the function is called. Here, 3 and 7 are arguments. When the function runs, x takes the value 3 and y takes the value 7, producing a return value of 21.

Question 2: BASIC CALCULATION

Write a function declaration called 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.
Show answer
The function declaration is: function celsiusToFahrenheit(celsius) { return celsius * 9 / 5 + 32; }. Calling celsiusToFahrenheit(25) evaluates to 25 × 9 / 5 + 32 = 45 + 32 = 77. The function returns 77, meaning 25°C equals 77°F. Because this is a declaration, it could be called before or after the function definition in your code due to hoisting.

Question 3: INTERMEDIATE

Consider the following code. Will it run successfully or produce an error? Explain your reasoning. console.log(square(4)); const square = function(n) { return n * n; };
Show answer
This code will produce a ReferenceError. The function is written as a function expression assigned to a const variable. Variables declared with const are not hoisted in a usable way—they exist in the temporal dead zone until the line where they are assigned. Since console.log(square(4)) appears before the assignment, JavaScript cannot find an initialized square variable. To fix this, you could either move the call below the definition or rewrite it as a function declaration.

Question 4: APPLIED

You're building a grade calculator for a class. Write a function expression stored in a 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.
Show answer
One correct solution: const getLetterGrade = function(score) { if (score >= 90) return "A"; if (score >= 80) return "B"; if (score >= 70) return "C"; if (score >= 60) return "D"; return "F"; };. Calling getLetterGrade(84) returns "B" because 84 is not ≥ 90 (fails first check) but is ≥ 80 (passes second check). The function uses early returns, which means each if exits the function immediately when its condition is true, so no else blocks are needed.

Question 5: CRITICAL THINKING

A teammate argues that you should always use function declarations because hoisting makes the code more flexible. Another teammate argues that you should always use 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.
Show answer
Function declarations are advantageous because hoisting lets you organize code with calling logic at the top and helper functions at the bottom, which some developers find more readable. However, hoisting can be a disadvantage because it makes it less obvious where a function is actually defined, potentially causing confusion in large files. Function expressions with const enforce a top-to-bottom reading order that prevents usage before definition, which reduces bugs, and const prevents accidental reassignment of the function name. However, this strict ordering can feel restrictive when you want two functions to call each other (mutual recursion). A good scenario for declarations is a utility file where you want all helper functions available throughout the module. A good scenario for expressions is when passing a function as a callback to addEventListener or setTimeout, where the function is a value being handed to another function.

SUMMARY

Lesson Summary

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.

Varsity Tutors • JavaScript • Function Declarations & Expressions