How does hoisting affect function declarations and expressions?
TL;DR
Hoisting in JavaScript means that function declarations are moved to the top of their containing scope during the compile phase, making them available throughout the entire scope. This allows you to call a function before it is defined in the code. However, function expressions are not hoisted in the same way. If you try to call a function expression before it is defined, you will get an error because the variable holding the function is hoisted but not its assignment.
// Function declarationconsole.log(foo()); // Works finefunction foo() {return 'Hello';}// Function expressionconsole.log(bar()); // Throws TypeError: bar is not a functionvar bar = function () {return 'Hello';};
Hoisting in JavaScript
Function declarations
Function declarations are hoisted to the top of their containing scope. This means you can call the function before it is defined in the code.
console.log(foo()); // Works finefunction foo() {return 'Hello';}
In the example above, the function foo
is hoisted to the top of its scope, so calling foo()
before its definition works without any issues.
Function expressions
Function expressions, on the other hand, are not hoisted in the same way. The variable that holds the function is hoisted, but its assignment is not. This means that if you try to call a function expression before it is defined, you will get an error.
console.log(bar()); // Throws TypeError: bar is not a functionvar bar = function () {return 'Hello';};
In this example, the variable bar
is hoisted to the top of its scope, but the assignment function() { return 'Hello'; }
is not. Therefore, calling bar()
before the assignment results in a TypeError
.
Differences between var
, let
, and const
It's also important to note the differences in hoisting behavior between var
, let
, and const
when used with function expressions.
var
: The variable is hoisted and initialized withundefined
.let
andconst
: The variables are hoisted but not initialized, leading to aReferenceError
if accessed before initialization.
console.log(baz); // undefinedvar baz = function () {return 'Hello';};console.log(qux); // ReferenceError: Cannot access 'qux' before initializationlet qux = function () {return 'Hello';};console.log(quux); // ReferenceError: Cannot access 'quux' before initializationconst quux = function () {return 'Hello';};