SKU // 44

Function Expressions

In JavaScript, a function is a value, just like a number or a string. That means you can store one in a variable, pass one into another function, or return one from a function. A function expression is a function written in a place where a value is expected, most often stored in a variable.

// Declaration vs Expression

// Function DECLARATION: a statement on its own
function multiply(a, b) {
  return a * b;
}

// Function EXPRESSION: a function used as a value, stored in a variable
const times = function(a, b) {
  return a * b;
};

console.log(multiply(4, 3), times(4, 3));
12 12

Both are called the same way, and both work the same when called. Once a function expression is stored in a variable, the variable name is how you call it.

Declaration Expression
Name after functionRequiredOptional (usually left out)
Ends with a semicolonNoYes (it is an assignment statement)
Callable before its lineYes (hoisted)No

// Anonymous Functions

The expression above has no name after the word function. It is an anonymous function: a function without a name. Functions stored in variables do not need names, because the variable provides one.

Function expressions can have a name, though. This is called a named function expression:

const add = function add(a, b) { return a + b; };

The inner name shows up in error messages, which helps debugging, and lets the function call itself:

const countdown = function tick(n) {
  if (n < 0) return;
  console.log(n);
  tick(n - 1);        // calls itself with a smaller number
};

countdown(2);
2 1 0

A function that calls itself is called recursive. The if (n < 0) return; line is essential: it is what makes the calls stop, just like a loop's condition.

// Expressions Use Semicolons

A function expression is part of an assignment statement (const x = ...;), so it ends with a semicolon after the closing brace, just like const n = 5; does. A declaration does not need one.

// The Big Difference: Hoisting

Declarations can be called before the line where they appear. Expressions cannot, because the variable does not hold the function until that line runs:

console.log(early());   // works
function early() { return "works"; }

console.log(late());    // fails
const late = function() { return "works"; };
works ReferenceError: Cannot access 'late' before initialization

That is the temporal dead zone from JS Let: late is a const, and it cannot be touched before its line.

Tip
Many developers prefer expressions with const precisely because of this: the code reads top to bottom, and a function cannot be used before it is defined. And as a bonus, const means the function cannot accidentally be replaced later.

// Functions Are Values

Because a function is a value, you can copy it to another variable:

const shout = function(text) {
  return text.toUpperCase() + "!";
};

const yell = shout;        // no parentheses: copies the function itself
console.log(yell("hey"));
HEY!

// Passing a Function to a Function (Callbacks)

A function can be passed as an argument to another function. The receiving function decides when to call it:

function run(fn) {
  return fn();
}

const sayHello = function() {
  return "Hello";
};

console.log(run(sayHello));    // pass the function, no ()
Hello

A function passed in like this is called a callback. You can also write the function right inside the call:

function repeat(times, action) {
  for (let i = 1; i <= times; i++) {
    action(i);
  }
}

repeat(3, function(n) {
  console.log("Lap " + n);
});
Lap 1 Lap 2 Lap 3

You have already seen this pattern with addEventListener("click", handleClick). Callbacks are everywhere in JavaScript: events, timers (JS Timers), and array methods all use them.

// Returning a Function from a Function

A function can build and return a brand new function. The returned function remembers the values that were around when it was made:

function makeMultiplier(factor) {
  return function(n) {
    return n * factor;
  };
}

const double = makeMultiplier(2);
const triple = makeMultiplier(3);
console.log(double(10), triple(10));
20 30
Note
A function that remembers variables from where it was created is called a closure. double still knows factor is 2, even though makeMultiplier finished running long ago. Closures are an advanced topic; for now, just notice that it works.

// Run It Right Away (IIFE)

Wrap a function expression in parentheses and add () to run it the moment it is defined. This is an Immediately Invoked Function Expression (IIFE), which you met in Function Invocation:

(function() {
  const secret = "hidden";
  console.log("Setup done");
})();
// secret does not exist out here
Setup done

You will see IIFEs in older code as a way to keep variables private, so they do not clash with other scripts. The theme script on these lesson pages uses one.

// When to Use Each

Next up, arrow functions give you a much shorter way to write function expressions, and they are what most modern code uses for callbacks.

// Common Mistakes

// Quick Check

Which kind of function can be called before the line where it is defined?

  1. A function declaration
  2. A function expression stored in const
  3. A function expression stored in let
  4. None of them
Show answer
A. Declarations are hoisted. Expressions only exist once their line has run.

What does this log?

function twice(fn, x) {
  return fn(fn(x));
}
const addThree = function(n) { return n + 3; };
console.log(twice(addThree, 10));
Show answer
16. The inner call gives addThree(10) = 13, then the outer call gives addThree(13) = 16.

What does const g = makeMultiplier(5); console.log(g(4)); log, using the makeMultiplier function above?

Show answer
20. makeMultiplier(5) returns a function that remembers factor is 5. Calling it with 4 gives 4 × 5.

// Try It

  1. Click Open Playground. Rewrite double as a const function expression and check it still works
  2. Call your function expression one line before it is defined and read the error
  3. Write applyTwice(fn, x) that returns fn(fn(x)). Test it with a doubling function
  4. Write makeGreeter(greeting) that returns a function taking a name, then make a "Hi" greeter and a "Welcome" greeter
// Video Walkthroughs
Last updated: Oct 10, 2026, 12:52 AM ET