cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Function expressions & callbacks

Learn how JavaScript treats functions as values: store them in variables, pass them into other functions, return them, and use callbacks safely.

By the end, you can
  • 01
    Create function valuesWrite function expressions and compare them with declarations.
  • 02
    Pass behavior aroundStore functions in variables, objects, and arguments without calling too early.
  • 03
    Use callbacksTrace a function that receives another function and calls it later.

Functions are values

You already know that a function packages code behind a name. This lesson adds the next idea: in JavaScript, a function is also a value. You can store it in a variable, keep it in an object, pass it to another function, return it from a function, or put it in an array just like a number or a string.

That is why typeof a function is "function", as the Data types lesson teaches. JavaScript gives function values one special power: you can call them with parentheses. Without parentheses, you are moving the recipe card around. With parentheses, you are cooking the recipe now.

The short version

A function expression creates a function value. A callback is a function value you pass to another function so it can call you back at the right moment.

Real-life analogyA function is a recipe card

Imagine a recipe card for pancakes. You can file it in a folder, mail it to someone, or hand it to a cook. None of those actions make pancakes yet. Cooking happens only when someone follows the card. Function values work the same way: add is the card; add(2, 3) follows it now.

In real life: A recipe card
In JavaScript: A function value
In real life: Putting the card in a folder
In JavaScript: Storing it in a variable or object
In real life: Handing the card to a friend
In JavaScript: Passing it as an argument
In real life: Cooking from the card
In JavaScript: Calling it with parentheses

Where the analogy stops: A recipe card is paper and a function is executable code. The analogy is about moving instructions around before anyone follows them.

This unlocks most modern JavaScript style. Array methods, browser events, timers, and many libraries ask you to provide behavior as a function. The deeper Higher-order functions lesson returns to this idea later; here we focus on the beginner skill: recognizing whether a function is being stored, passed, or called.

Function expressions

CORE IDEA

A function declaration starts a statement:

Function declarationPop out in the code editor (opens in a new tab)JavaScript
function add(a, b) {
  return a + b;
}

A function expression creates a function value inside another expression. Most beginners first see it assigned to a const variable:

Function expressionPop out in the code editor (opens in a new tab)JavaScript
const add = function (a, b) {
  return a + b;
};

console.log(add(2, 3)); // 5

The right side, function (a, b) { ... }, is the value. The left side, add, is the variable that stores it. This is the same const rule from the Variables lesson: the variable cannot be reassigned, but the function value can still run whenever you call it.

Function expressions often appear where a value is expected: after =, inside an object, inside an array, or between the parentheses of a function call. Sort the shapes below before you read the answer explanations.

Declaration or expression?
  • function a() {};
  • const b = function () {};
  • setTimeout(function () {}, 0);
  • const c = function named() {};
  • (function () {})();
  • const tools = { run: function () {} };
Try it yourself
0 of 6 correct

Sort each line by the function shape it uses. The explanations point to the clue.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Declarations vs expressions

STEP THROUGH

Declarations and expressions can both create callable functions, but they are prepared differently before the script runs. A declaration is hoisted with its body, so it can be called before its line. A const function expression follows const rules: the variable is in the temporal dead zone until its line runs. An older var function expression starts as undefined, so calling it too early throws a different error.

Call before the definition line
Step 0 of 3Ready
Your turn: follow the blue line

Choose a setup, then step through what happens when line 1 calls a function before the definition line.

Running in
  1. script
Next: line 3
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
sayHello();   console.log("hello from declaration");}
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Choose which shape line 3 uses

Changing the shape starts a fresh replay. Predict line 1 before you step.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Function declaration vs function expression
QuestionDeclarationExpression
Call before its lineUsually works; declarations are hoisted with their function bodyconst/let expressions throw ReferenceError before initialization; var expressions start as undefined
NameThe function’s name is requiredCan be anonymous, inferred from a variable, or explicitly named for debugging
Typical useReusable named action in a scopePassing behavior, storing in objects, choosing one function from many
StyleReads like a sentence: here is a functionReads like a value: store this function in a variable
Verified errors

In the test for this lesson, calling a const function expression before initialization throws ReferenceError: Cannot access 'sayHello' before initialization. Calling a var expression before assignment throws TypeError: sayHello is not a function. TypeScript may warn before you run similar code; JavaScript’s runtime errors are shown in the replay.

When should you choose which? Use a declaration when you want a named helper to read like a normal part of the surrounding code. Use a function expression when the function is being treated as data: stored in a lookup, passed to a function, or created only for one spot.

First-class functions

INTERACTIVE

First-class means functions get the same basic rights as other values. A number can be stored in a variable, passed to a function, returned, and kept in an object. A function can too. That is not a fancy pattern; it is a normal language rule.

Choose a function value
Operations lookupPop out in the code editor (opens in a new tab)JavaScript
function add(a, b) { return a + b; }function subtract(a, b) { return a - b; }function multiply(a, b) { return a * b; } const operations = { add, subtract, multiply };const chosen = operations.add; function calculate(operation, left, right) {  return operation(left, right);} console.log(calculate(chosen, 8, 3));
Real calladd

calculate(add, 8, 3)

Result: 11

Try it yourself

The object stores three function values. The selected value is passed into calculate, then calculate calls it with 8 and 3.

A tiny strategy lookup: choose behavior by choosing a function value.

The object in the playground is a small version of a pattern you will use constantly: choose data, then choose behavior. A calculator can pick operations.add; a menu can pick a handler for the current command; a validation system can keep one function per rule.

Passing vs calling

calculate(add) passes the function value. calculate(add()) calls add immediately and passes its result. If the result is not a function, calculate cannot call it. Parentheses are the difference.

Callbacks

STEP THROUGH

A callback is a function you pass to another function so that other function can call it. The receiving function may call it right away, during a loop, after a timer, or when a user clicks. The key idea is control: you hand over the recipe card, and the other function decides when to use it.

Real-life analogyA callback is leaving your phone number

When a restaurant is full, you leave your phone number. You do not decide the exact minute they call; they call when the table is ready. A callback works like that: you hand over a function, and the other code calls it at the right time.

In real life: You leave your number at a restaurant
In JavaScript: You pass a function as an argument
In real life: The restaurant calls when the table is ready
In JavaScript: The receiving function calls your callback when it chooses
In real life: You do not call yourself from the host stand
In JavaScript: Passing a function is different from calling it immediately

Where the analogy stops: A phone call happens later in real life. Some JavaScript callbacks, like the repeat example, run synchronously before the outer function returns.

repeat calls a callback
Step 0 of 10Ready
Your turn: follow the blue line

A callback is a function you hand to someone else. Step through repeat to see that repeat chooses when to call it.

Running in
  1. script
Next: line 7
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
function repeat(times, action) {  for (let count = 1; count <= times; count++) {    action(count);  }}   console.log("Turn " + number);});
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Change the first argument to repeat

Each count calls the same callback with a new argument.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

The call stack shown in the replay says script → repeat → action. That means the main script called repeat, and repeat called the callback. This is still synchronous: the loop finishes before the next line after repeat(...) would run.

Arrays use the same shape. You will learn map, filter, and reduce in Stage 3, but this simple forEach already shows the callback idea:

forEach also receives a callbackPop out in the code editor (opens in a new tab)JavaScript
const names = ["Ada", "Grace", "Linus"];

names.forEach(function greet(name) {
  console.log("Hi, " + name);
});

A timer callback runs later. This lesson is not the event loop lesson, so keep the honest summary small: setTimeout receives a function now, the host waits, then it calls that function later.

Async teaser: callback laterPop out in the code editor (opens in a new tab)JavaScript
console.log("first");

setTimeout(function onTimer() {
  console.log("later");
}, 0);

console.log("second");

Browser events follow the same idea. A later lesson covers events in detail, but button.addEventListener("click", callback) literally means: when the click happens, call this function.

Anonymous functions and named function expressions

An anonymous function has no name after the function keyword. It is common when the function is short and used right where it is created:

Anonymous function passed inlinePop out in the code editor (opens in a new tab)JavaScript
repeat(3, function (number) {
  console.log("Turn " + number);
});

An anonymous function is like a recipe card without a title. That can be perfectly fine for a small one-off callback. But names help humans. They appear in stack traces and make recursion easier:

Named function expressionPop out in the code editor (opens in a new tab)JavaScript
const factorial = function fact(n) {
  if (n <= 1) return 1;
  return n * fact(n - 1);
};

console.log(factorial(4));
console.log(typeof fact);

In that code, the outer variable is factorial. The inner function name fact is visible inside the function body, so the function can call itself. Outside, typeof fact prints "undefined". When you are reading an error stack, a helpful name is easier to recognize than anonymous; that connects directly to the Reading error messages lesson.

Where you’ll use this

Function expressions and callbacks show up anywhere code needs to customize behavior without rewriting the whole tool. Here are three beginner-friendly patterns:

  • Lookups: keep operations in an object, then choose one by name instead of writing a long if chain.
  • Repeated work: write repeat(times, action) once, then pass a different action for printing, drawing, or saving.
  • Later work: pass a function to a timer or event listener so the host can call it when time passes or the user acts.
Returning functions comes next

A function can also return another function. When the returned function keeps variables from where it was created, that is a closure. You only need the idea here: returning a function is allowed because functions are values.

Common misconceptions

“A function expression runs when it is assigned.”

Assignment stores the function value. The body runs only when something calls it with parentheses.

“Callbacks are always asynchronous.”

Timer and event callbacks run later, but forEach and the lesson’s repeat callback run synchronously during the current call.

“Function declarations and expressions hoist the same way.”

Declarations are callable before their line. A const expression is not initialized yet, and a var expression is only undefined early.

“Anonymous means unusable for debugging.”

Modern engines can infer many names from variables, but an explicit name still makes stack traces and recursion clearer.

“Passing a function and passing its result are close enough.”

They are opposite actions. calculate(add) hands over behavior; calculate(add()) runs add too soon.

Practice: function values

5 EXERCISES
Exercise 1 · Warm-upPredict the early-call error

Predict the error name before running the snippet.

Starter codePop out in the code editor (opens in a new tab)JavaScript
greet();
const greet = function () {
  console.log("hi");
};

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeWrite applyTwice

    Write a function that takes a starting value and a callback, then applies the callback twice.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    function applyTwice(value, action) {
      return action(action(value));
    }
    
    function double(number) {
      return number * 2;
    }
    
    console.log(applyTwice(5, double));

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFix calculate(add())

      The code passes the result of add() instead of the function. Fix it so calculate receives the function.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      console.log(calculate(add()));

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeTurn a declaration into an expression

        Explain what changes when a hoisted declaration becomes a const function expression.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        shout("ready");
        
        const shout = function (word) {
          return word.toUpperCase();
        };

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeBuild an operations lookup

          Create an object with add, subtract, and multiply functions. Pick multiply and call it.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const operations = {
            add: function (a, b) { return a + b; },
            subtract: function (a, b) { return a - b; },
            multiply: function (a, b) { return a * b; },
          };
          
          const chosen = operations.multiply;
          console.log(chosen(6, 7));

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            7 QUESTIONS

            Read each snippet carefully. Parentheses and declaration shape matter.

            Lesson quiz · 7 questionsScore: first tries count
            1. Question 1 of 7What is a function expression?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does this declaration print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              sayHi();
              function sayHi() {
                console.log("hi");
              }

              Choose an answer to see the explanation.

            3. Question 3 of 7What happens here?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(typeof choose);
              var choose = function () {};

              Choose an answer to see the explanation.

            4. Question 4 of 7What does the correct calculate(add) call print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function add(a, b) { return a + b; }
              function calculate(operation) {
                return operation(4, 2);
              }
              console.log(calculate(add));

              Choose an answer to see the explanation.

            5. Question 5 of 7What does this callback print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function repeat(times, action) {
                for (let count = 1; count <= times; count++) {
                  action(count);
                }
              }
              repeat(2, function (n) {
                console.log("#" + n);
              });

              Choose an answer to see the explanation.

            6. Question 6 of 7What does this print outside the named function expression?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const factorial = function fact(n) {
                return n <= 1 ? 1 : n * fact(n - 1);
              };
              console.log(typeof fact);

              Choose an answer to see the explanation.

            7. Question 7 of 7Which statement about callbacks is true?

              Choose an answer to see the explanation.

            Key takeaways

            • Functions are values, so they can be stored, passed, returned, and kept in objects.
            • A function expression creates a function value inside a larger expression.
            • Declarations are callable before their line; const function expressions are not.
            • Callbacks are function values passed to another function to be called at the right moment.
            • Anonymous functions are fine for short inline callbacks; names help stack traces and recursion.

            Remember the one-liner.
            A function expression is a function value; a callback is that value handed to someone else to call.

            Up next: Arrow functions, where you’ll learn shorter callback syntax and the important differences arrows bring.

            CompleteFrontend Clear concepts. Working examples.