The behavior you're observing is a core aspect of JavaScript's hoisting mechanism, which applies differently to var declarations and function declarations.
Here's a breakdown:
Hoisting of var Variables
When JavaScript processes your code, var declarations are "hoisted" to the top of their scope (global or function scope). However, only the declaration is hoisted, not the assignment. Crucially, var variables are also initialized with undefined during the hoisting phase.
Consider your code:
JavaScript interprets this as if it were:
That's why console.log(num) on the first line outputs undefined instead of throwing an error. The variable num exists, but its assigned value of 10 hasn't been reached yet.
Hoisting of function Declarations
In contrast, function declarations are hoisted in their entirety – both the function's name and its body are moved to the top of their scope. This means the entire function is available for use before it appears in the code.
For your greet function:
JavaScript effectively processes this as:
This allows greet() to be invoked successfully on the first line, returning "Hello, World!".
Summary of Differences
varvariables: Declaration is hoisted, initialized toundefined. Assignment stays in place.functiondeclarations: Entire function (declaration and definition) is hoisted, making it fully available.
How let and const Differ
let and const also experience hoisting, but they behave differently from var:
- No Default Initialization: While their declarations are hoisted,
letandconstvariables are not initialized toundefined. - Temporal Dead Zone (TDZ): If you try to access a
letorconstvariable before its actual declaration in the code, JavaScript will throw aReferenceError. This period between the start of the scope and the actual declaration is called the Temporal Dead Zone.
Example with let and const:
This behavior of let and const helps catch potential bugs related to accessing uninitialized variables and makes JavaScript code more predictable, which is why let and const are generally preferred over var in modern JavaScript.