This lesson is about the concept of hoisting in JavaScript which will come into play in the module project. Hard-to-find bugs sometimes result from a poor understanding of hoisting.
Hoisting has the effect of making it seem like the declaration of variables and functions have moved to the top of their enclosing scope, which can be either the global scope or the function scope in which they are declared.
How Functions Are Hoisted
Some things, like function declarations, are hoisted. Since functions are hoisted, you can call them even though the definition comes after the function call:
greet();
function greet() {
console.log('hello world');
}
This code runs successfully, even though the function is defined after the function call. That said, "after" is not the right word here, because the function is hoisted, so in effect, the function is actually defined before it's called, even though in the source code, it appears after.
If hoisting did not happen, like in Python, for example, you would have to write your code in this order:
function greet() {
console.log('hello world');
}
greet();
This is because Python does not hoist functions, so you have to define them before you call them.
That said, you can also define functions as variables with function expressions, and those are not hoisted:
greet(); // Uncaught ReferenceError: Cannot access 'greet' before initialization
const greet = function () {
console.log('hello world');
};
This code raises an error because the function is not hoisted since the variable has not been initialized yet, so it cannot be accessed.
How Variables Are Hoisted
Variables are hoisted differently depending on whether they are defined with var, let and const.
There are two stages to creating any new variable, even though you usually only see it on one line:
- Declaration i.e.
let x - Initialization i.e.
x = 1
You usually see it all on one line let x = 1.
Variables Declared With Var
Though var has not been used in JavaScript 101 and will not be used in 201, 301, or probably any course from here on out, you'll still see it in the wild. Some old code-bases will still use var, so it's good to know how it behaves.
When using var, the declaration is hoisted, but the initialization is not.
console.log(x); // undefined
var x = 1;
console.log(x); // 1
The declaration is hoisted but not initialized, which is why it's value is undefined. The first console.log() does not raise an error, but logs undefined. It is then initialized with the value 1 and so the second log outputs 1.
If you used let or const the first line would raise an error.
Hoisting can be the source of some confusing bugs!
Variables Declared With Let or Const
const and let are actually hoisted, much like `var, but are not initialized with a default value, and will throw an error if the variable is accessed before it's actually initialized in the source code:
console.log(greeting); // Uncaught ReferenceError: Cannot access 'greeting' before initialization
const greeting = 'hello world';
Since the code starts with referencing a variable that is defined below it, the JavaScript interpreter raises an error. There is no greeting , yet. This is the same for let.
const and let are actually hoisted but cannot be accessed before their declaration due to the temporal dead zone.
The Temporal Dead Zone (TDZ) in JavaScript is a period from the start of a block until the declaration of a let or const variable within that block is reached. During the TDZ, these variables are in scope but not yet initialized, making them inaccessible and leading to a reference error if used before their declaration. This mechanism helps catch errors and enhances code readability by preventing the use of variables before they are formally declared.
Learn by Doing
Copy the examples from this lesson and get them working in your labs. Make a few variations, too. Try to get a feel for how hoisting works with var, let, and const.
If you're doing this course step-by-step, and especially if you're in the mentorship program, please be sure to push your work to GitHub when you're done.
Check out the MDN docs for more info.
Summary: What Does Hoisting Mean in Javascript
You've just tackled the concept of hoisting in JavaScript. You've:
- Recognized that function declarations are hoisted entirely, allowing them to be called before they're defined in the code.
- Differentiated between function expressions assigned to variables, which are not hoisted, resulting in a reference error if they're called before the variable is initialized.
- Discovered that variable declarations using
varare hoisted but only their declaration part, not the initialization, leading to them returningundefinedif accessed before being set. - Learned that
letandconstdeclarations are also hoisted but are not accessible before their actual declaration within the source code due to the temporal dead zone.
Remember, hoisting nuances can lead to subtle bugs, so it's good to experiment and read documentation like the MDN docs on hoisting to solidify your understanding.