Hoisting
Hoisting
hoisting is the processing of declarations before any code is executed.
What's a declaration though?
- a declaration is a way of telling the interpreter (or compiler) that a name or identifier exists
 - we learned a few ways of declaring names in JavaScript (the 1st is easy, the 2nd, a bit tricky)… what were they? →
- variable declarations (using 
const,let, andvar) - function declarations (using 
function f(x) {}) 
 - variable declarations (using 
 
Hoisting basically brings declarations to the top of the current scope.  What does that mean for us? →
- some declarations do not have to occur before they are used!
 - we already saw this with functions declarations...
 
Hoisting and Functions
So… we basically know what happens here. What's the output of the following code examples? →
f();
function f() {
	console.log("TO THE TOP, PLZ!")
}
output: TO THE TOP, PLZ!
f();
var f = function() {
	console.log("TO THE TOP, PLZ!")
}
output: TypeError: undefined is not a function
f();
output: ReferenceError: f is not defined
Hoisting and Functions SOME MORE!
What's the output of this code? →
function outer() {
	inner();
	function inner() {
		console.log('hello');	
	}
}
outer();
hello is printed out. What happens if we add in a call to inner at the end, outside of the function?
// same as above (function outer() ... )
// but add the line below at the very end
inner();
ReferenceError - function declarations are hoisted to the top of their current scope (not to the top of the global scope)
Great! But What About varDeclarations?
(We'll see why var f = function ... behaves the we way it does)
var Examples
Treating each code example as a completely separate program, what is the output of the following lines of code?→
console.log(x);
// variable not yet declared (easy)
ReferenceError: x is not defined
var x;
console.log(x);
// x is declared before ... works obvs!
undefined
// so... what do we get here?
console.log(x);
var x;
undefined
Note that the last example would be an error if using let (or const)
var Declarations are Hoisted
console.log(x);
console.log(y);
var x;
var y;
In the above example:
- the variable declarations are taken from the regular top-to-bottom flow
 - … and they are treated as if they were moved to the beginning of their enclosing scope
 - consequently, this prints out 
undefinedtwice rather thanReferenceError 
How About Initializing a Variable Along with var?
Let's start simple. What's the output of this code?
var x = 5;
console.log(x);
// no surprise here!
5
But how about this? →
console.log(x);
var x = 5;
// oof. what!?
undefined
var and Initialization
vardeclarations are hoisted- but the initialization is executed in the location of the program where the initialization statement is actually placed
 - soooo… that means:
 
console.log(x);
var x = 5;
- is executed as:
 
var x;
console.log(x);
x = 5;
Another Note on var and Hoisting
This probably doesn't matter since, we all know that you should never declare a variable without var, but:
- implicit variable declarations are not hoisted!
 - the following gives us a 
ReferenceError 
// (all we did here was take out var!)
console.log(x); // oops ... ReferenceError
x = 5;
What About let and const?
As we saw previously, let and const have a Temporal Dead Zone →
- a variable declared with 
letandconstcannot be accessed…- between the time that the containing scope is entered
 - and the actual 
letorvardeclaration 
 - however… an identifier is actually created for it at the beginning of the scope! you just can't use it yet!
 - (so it's sort of hoisted; there seems to be some debate on the terminology for this)
 - consequently, this code gives an error:
console.log(x); let x = 5; 
Hoisting Summary
This is all you need to know about hoisting:
letandconstdeclared variables cannot be accessed until their declaration (this is actually sane)vardeclarations and function declarations are brought to the beginning of their enclosing scope- all function declarations are hoisted
 vardeclarations are hoisted, but the assignment part occurs where the original statement was locatedvardeclarations that haven't been assigned a value yet are initialized withundefined(just likelet)
- implicit variable declarations (no 
const,let, orvar) are not hoisted (but you always uselet,constorvar, so not relevant, right?) 
Hoisting Example 1
What's the output of the following code? →
var num = 1000; 
f(); 
function f(){ 
	console.log(num)
	var num = 5;
};
undefined
- the global 
numis not used - instead, 
numwithin the function is hoisted to the top of its enclosing scope, the function,f - but note the initialization is executed in the place where it occurs… consequently, 
undefined 
Hoisting Example 2
What's the output of the following code? →
console.log(f);
var f = function(x) {
	console.log("hello " + x);
}
- yup, still 
undefined- the declaration is hoisted - … but the initialization to a value is not
 
// it's executed as if it were
var f;
console.log(f);
f = function(x) {
	console.log("hello " + x);
}
Hoisting Example 3
What's the output of this code? →
var inner = 1000;
function outer () {
    inner = 5;
    function inner() {}
}
outer();
console.log(inner);
- the output is 
1000 - the function declaration of 
inneris hoisted to the top of the enclosing scope - which renders the first line of the function, 
inner = 5, a reassignment of the localinner, not the global 
Hoisting Example 4
What's the output of this code? →
console.log(f);
const f = function() {
    console.log('I am function!');
}
ReferenceError   
(temporal dead zone for const and let; used before declared)
Back to an Earlier Mystery
And that's why the following gives us undefined is not a function →
f();
var f = function(x) {
	console.log("hello " + x);
}
- we know that the declaration of 
fis hoisted - but it has no value at the point that it is invoked/called (it's 
undefined) - consequently, the program is attempting to use 
undefinedas a function 
Whew! That Seemed Unnecessarily Complicated.
Why even? ಠ_ಠ
No Seriously…
Hoisting. Why? →
- generally a top-down approach is taken to programming
- so it may make sense for the "main" part of the program to go on top, calling functions elsewhere
 - those functions are likely to be declared below main
 - so it's more natural… ¯\_(ツ)_/¯ (maybe)
 
 - as for 
var, I don't know if I can excuse that! 
- according to this SO article….
 - it may possibly just be due to the interpreter implementation: scan source for variable and function declarations first, then execute code next
 
Easy, Right?
A lot of the design decisions in JavaScript seemed to be made for ease of use
Hoisting Can Lead to Tricky Situations
Like the one we saw before:
var num = 1000; 
f(); 
function f(){ 
	console.log(num)
	var num = 5;
};
How can we get around this ambiguity? →
Always declare your variables at the beginning of your function!
Aaaaand… possibly, avoid using var; use let and const instead!
                    
                
                
            
        
浙公网安备 33010602011771号