0
0
Javascriptprogramming~15 mins

Function expression in Javascript - Deep Dive

Choose your learning style9 modes available
Overview - Function expression
What is it?
A function expression is a way to create a function and store it in a variable. Unlike a regular function declaration, it does not have a name by itself and can be anonymous. You can use this stored function just like any other function by calling the variable. It allows functions to be treated like any other value in JavaScript.
Why it matters
Function expressions let you create functions dynamically and pass them around easily, like passing a note in class. Without them, you would have to name every function upfront and could not use functions as flexible building blocks. This flexibility is key for modern JavaScript features like callbacks, event handlers, and functional programming styles.
Where it fits
Before learning function expressions, you should understand basic function declarations and variables. After this, you can explore arrow functions, callbacks, and higher-order functions which build on function expressions.
Mental Model
Core Idea
A function expression is a function created inside an expression and stored as a value you can use later.
Think of it like...
It's like writing a recipe on a sticky note and putting it in your pocket to use whenever you want, instead of having it fixed on a wall with a title.
Variable holding function:

  +----------------+
  |  myFunc        |
  |  (variable)    |
  +-------+--------+
          |
          v
  +----------------+
  | function() {   |
  |   // do stuff  |
  | }              |
  +----------------+
Build-Up - 7 Steps
1
FoundationBasic function declaration review
πŸ€”
Concept: Understand how normal functions are declared and called.
In JavaScript, you can create a function with a name like this: function greet() { console.log('Hello!'); } greet(); // Calls the function and prints 'Hello!' This is a function declaration with a fixed name 'greet'.
Result
The console shows: Hello!
Knowing how functions are declared helps you see the difference when functions are created as expressions.
2
FoundationVariables can hold values
πŸ€”
Concept: Variables can store different types of values, including numbers, strings, and functions.
You can store values in variables: const number = 5; const text = 'Hi'; Variables hold data you can use later.
Result
Variables 'number' and 'text' hold 5 and 'Hi' respectively.
Understanding variables as containers prepares you to store functions in them.
3
IntermediateCreating a function expression
πŸ€”Before reading on: do you think a function expression needs a name or can it be anonymous? Commit to your answer.
Concept: Functions can be created without names and assigned to variables as expressions.
You can create a function and assign it to a variable: const greet = function() { console.log('Hello from function expression!'); }; greet(); // Calls the function Here, the function has no name and is stored in 'greet'.
Result
The console shows: Hello from function expression!
Knowing functions can be anonymous and stored in variables unlocks flexible coding patterns.
4
IntermediateUsing function expressions as values
πŸ€”Before reading on: can function expressions be passed as arguments to other functions? Commit to your answer.
Concept: Function expressions can be passed around like any other value, enabling callbacks and dynamic behavior.
Example of passing a function expression: function runAction(action) { action(); } runAction(function() { console.log('Running action!'); }); The function expression is passed directly as an argument.
Result
The console shows: Running action!
Understanding functions as values is key to event-driven and asynchronous programming.
5
IntermediateNamed function expressions
πŸ€”
Concept: Function expressions can have names, which help with debugging and recursion.
You can name a function expression: const factorial = function fact(n) { if (n <= 1) return 1; return n * fact(n - 1); }; console.log(factorial(5)); // 120 The name 'fact' is local to the function body.
Result
The console shows: 120
Knowing named function expressions helps with self-reference and clearer error messages.
6
AdvancedDifferences from function declarations
πŸ€”Before reading on: do function expressions get hoisted like function declarations? Commit to your answer.
Concept: Function declarations are hoisted and available before code runs; function expressions are not hoisted and only exist after assignment.
Example: sayHi(); // Works because of hoisting function sayHi() { console.log('Hi!'); } // But this fails: sayHello(); // Error: sayHello is not a function const sayHello = function() { console.log('Hello!'); };
Result
First call prints 'Hi!'; second call throws an error.
Understanding hoisting differences prevents common bugs with function usage order.
7
ExpertFunction expressions in closures and memory
πŸ€”Before reading on: do function expressions create new scopes and can they capture variables? Commit to your answer.
Concept: Function expressions create closures that remember variables from their creation context, enabling powerful patterns.
Example: function makeCounter() { let count = 0; return function() { count++; console.log(count); }; } const counter = makeCounter(); counter(); // 1 counter(); // 2 The function expression remembers 'count' even after makeCounter finishes.
Result
The console shows 1 then 2 on successive calls.
Knowing function expressions create closures explains how private state and advanced patterns work.
Under the Hood
When JavaScript runs a function expression, it creates a function object in memory and assigns it to the variable. This function object can be called later. Unlike declarations, function expressions are not hoisted, so the variable holds 'undefined' until the assignment runs. If the function expression is inside another function, it forms a closure capturing variables from the outer scope, preserving their values even after the outer function ends.
Why designed this way?
Function expressions were designed to treat functions as first-class values, allowing them to be stored, passed, and returned like any other data. This design supports flexible programming styles like callbacks and functional programming. The lack of hoisting for expressions avoids confusion about when functions become available, making code behavior more predictable.
Code flow:

+-------------------+
| Variable declared  |
| (undefined initially)|
+---------+---------+
          |
          v
+-------------------+
| Function object    |
| created at runtime |
+---------+---------+
          |
          v
+-------------------+
| Variable points to |
| function object    |
+-------------------+

Closure capture:

Outer function scope variables
        |
        v
+-------------------+
| Function expression|
| remembers variables|
+-------------------+
Myth Busters - 4 Common Misconceptions
Quick: Do function expressions get hoisted like function declarations? Commit to yes or no.
Common Belief:Function expressions are hoisted and can be called before they appear in code.
Tap to reveal reality
Reality:Function expressions are NOT hoisted; the variable is undefined until assignment runs.
Why it matters:Calling a function expression before assignment causes runtime errors, confusing beginners.
Quick: Can a function expression be called without assigning it to a variable? Commit to yes or no.
Common Belief:You must always assign a function expression to a variable to use it.
Tap to reveal reality
Reality:Function expressions can be used immediately without assignment, called immediately (IIFE).
Why it matters:Missing this limits understanding of patterns like immediately invoked function expressions used for isolation.
Quick: Does naming a function expression make it globally accessible? Commit to yes or no.
Common Belief:Naming a function expression creates a global function with that name.
Tap to reveal reality
Reality:The name in a named function expression is local to the function itself, not global.
Why it matters:Assuming global scope leads to unexpected errors and polluting global namespace.
Quick: Are function expressions always anonymous? Commit to yes or no.
Common Belief:Function expressions cannot have names; they are always anonymous.
Tap to reveal reality
Reality:Function expressions can be named, which helps with recursion and debugging.
Why it matters:Not knowing this misses out on better debugging and recursive function patterns.
Expert Zone
1
Named function expressions create a local name binding only visible inside the function, which helps recursion without polluting outer scopes.
2
Function expressions inside loops can cause subtle bugs if not handled carefully due to variable capture in closures.
3
The difference in hoisting behavior between declarations and expressions affects module loading and initialization order in complex apps.
When NOT to use
Avoid function expressions when you need hoisting to organize code top-down; use function declarations instead. For very short functions, arrow functions are often clearer and more concise. Also, avoid anonymous function expressions when debugging is critical; prefer named expressions.
Production Patterns
Function expressions are widely used for callbacks in event handlers, promises, and asynchronous code. They enable modular code by passing behavior as arguments. Named function expressions help with stack traces in error logging. Immediately invoked function expressions (IIFE) are used to create isolated scopes in legacy code.
Connections
Arrow functions
Arrow functions are a concise syntax for function expressions with lexical 'this' binding.
Understanding function expressions is essential to grasp arrow functions, which build on the same concept but change behavior subtly.
Closures
Function expressions often create closures by capturing variables from their surrounding scope.
Knowing function expressions helps understand how closures preserve state and enable private variables.
Mathematical lambda calculus
Function expressions in programming are practical implementations of anonymous functions from lambda calculus.
Recognizing this connection reveals the deep theoretical foundation of treating functions as first-class values.
Common Pitfalls
#1Calling a function expression before it is assigned.
Wrong approach:sayHello(); const sayHello = function() { console.log('Hello!'); };
Correct approach:const sayHello = function() { console.log('Hello!'); }; sayHello();
Root cause:Misunderstanding that function expressions are not hoisted and the variable is undefined before assignment.
#2Assuming the name in a named function expression is globally accessible.
Wrong approach:const f = function foo() {}; console.log(foo); // ReferenceError
Correct approach:const f = function foo() {}; console.log(f); // Works, foo is local inside function only
Root cause:Confusing function expression's internal name scope with global scope.
#3Using anonymous function expressions without names in recursive functions.
Wrong approach:const factorial = function(n) { if (n <= 1) return 1; return n * factorial(n - 1); };
Correct approach:const factorial = function fact(n) { if (n <= 1) return 1; return n * fact(n - 1); };
Root cause:Not naming the function expression causes recursion to rely on outer variable, which can break if reassigned.
Key Takeaways
Function expressions create functions as values that can be stored, passed, and used flexibly.
They differ from function declarations mainly in hoisting and naming behavior.
Function expressions enable powerful patterns like callbacks, closures, and dynamic behavior.
Named function expressions improve recursion and debugging without polluting outer scopes.
Understanding function expressions is foundational for mastering modern JavaScript programming.