First-Class Functions
Functions are fundamental building blocks in JavaScript. But have you ever wondered why sometimes you can call a function before you define it, and other times you can't? This difference often boils down to how the function is created. Let's dive in!
Statement vs. Expression: The Hoisting Puzzle
One of the most crucial differences between the two main ways of creating functions lies in hoisting. Hoisting is JavaScript's behavior of moving declarations (like function declarations and var variables) to the top of their scope before code execution.
The difference between function statement and function expression is hoisting.
Consider this:
Let's break down each type.
Function Statement (aka Function Declaration)
This is the classic way to define a function.
| index.js | |
|---|---|
Key characteristics:
- Starts with the
functionkeyword. - Requires a function name (
greetin this case). - The entire function definition is hoisted, making it available throughout its scope even before the line it's defined on.
Function Expression
Here, a function is created and assigned to a variable. The function itself often doesn't have a name (making it anonymous), although it can (see Named Function Expression).
| index.js | |
|---|---|
Key characteristics:
- The function is treated like a value.
- It's assigned to a variable (
greetMe). - If using
var, the variable declaration (var greetMe) is hoisted, but the assignment (= function() {...}) is not. This is why you get aTypeErrorif you call it before the assignment line.greetMeexists but holdsundefinedinitially, not the function.
Anonymous Function
An anonymous function is simply a function without a name.
The anonymous function above is also a callback because it is passed to
setTimeout, which decides when to invoke it. See Callback Functions and
Anonymous Functions for the complete mental model,
including the crucial difference between passing fn and invoking fn().
Why the error?
Function statements require a name. Anonymous functions are typically used where functions are treated as values, like in function expressions or when passed as arguments.
Named Function Expression
This is similar to a function expression, but the function being assigned does have a name.
| index.js | |
|---|---|
Corner Case Gotcha
| index.js | |
|---|---|
Important
The name in a named function expression (innerGreet, xyz) is typically only available within the function's own scope. It's not created in the outer (global or enclosing) scope. You still call the function using the variable it was assigned to (greetYou, b).
Parameters vs. Arguments
These terms are often confused, but they have distinct meanings:
- Parameters are the names listed in the function definition. They act as placeholders or local variables within the function.
- Arguments are the actual values passed to the function when it is called (invoked).
| index.js | |
|---|---|
✨ First-Class Functions
In JavaScript, functions are "first-class citizens". This fancy term means you can treat functions just like any other value (like numbers, strings, or objects). This ability includes:
- Assigning functions to variables (as seen in Function Expressions).
- Passing functions as arguments to other functions.
- Returning functions from other functions.
This is a powerful concept that enables patterns like callbacks and higher-order functions.
➡️ Arrow Functions (ES6)
Introduced in ES6 (ECMAScript 2015), arrow functions provide a more concise syntax for writing function expressions. They also have some differences in how they handle the this keyword (which is a topic for another discussion).
Arrow functions are very common in modern JavaScript due to their brevity.