Hoisting in JavaScript
In this article, we will learn about what is hoisting in JavaScript. In?JavaScript, Hoisting is a kind of default behavior in which all the declarations either variable declaration or function declaration are moved at the top of the scope just before executing the program's code.
Chicken or the Egg?
There is a temptation to think that all of the code you see in a JavaScript program is interpreted line-by-line, top-down in order, as the program executes. While that is substantially true, there is one part of that assumption that can lead to incorrect thinking about your program.
Consider this code:
a = 2;
var a;
console.log(a);
What do you expect to be printed in the console.log(...) statement?
Many developers would expect undefined, since the var a statement comes after the a = 2, and it would seem natural to assume that the variable is redefined and thus assigned the default undefined. However, the output will be 2.
Consider another piece of code:
console.log(a);
var a = 2;
You might be tempted to assume that, since the previous snippet exhibited some less-than-top-down looking behavior, perhaps in this snippet, 2 will also be printed. Others may think that since a variable is used before it is declared, this must result in a ReferenceError being thrown.
Unfortunately, both guesses are incorrect. undefined is the output.
So, what's going on here? It would appear we have a chicken-and-the-egg question. Which comes first, the declaration ("egg"), or the assignment ("chicken")?
The Compiler Strikes Again
To answer this question, we need to understand that when JavaScript program executes then the JavaScript engine actually will compile your JavaScript code before it interprets it. Part of the compilation phase was to find and associate all declarations with their appropriate scopes.
So, the best way to think about things is that all declarations, both variables and functions, are processed first, before any part of your code is executed.
When you see var a = 2;, you probably think of that as one statement. But JavaScript actually thinks of it as two statements; var a; and a = 2;. The first statement, the declaration, is processed during the compilation phase. The second statement, the assignment, is left in place for the execution phase.
Our first snippet then should be thought of as being handled like this:
领英推荐
var a;
a = 2;
console.log(a);
...where the first part is the compilation and the second part is the execution.
Similarly, our second snippet is actually processed as:
var a;
console.log(a);
a = 2;
So, one way of thinking, sort of metaphorically, about this process, is that variable and function declarations are "moved" from where they appear in the flow of the code to the top of the code. This gives rise to the name hoisting.
In other words, the egg (declaration) comes before the chicken (assignment).
Functions First
Both function declarations and variable declarations are hoisted, but a subtle detail is that functions are hoisted first and then variables.
Consider:
foo(); //1
var foo;
function foo() {
? ?console.log(1);
}
foo = function() {
? ?console.log(2);
}
Here, 1 is printed instead of 2!?
This snippet is interpreted by the Engine as:
function foo() {
console.log(1);
}
foo(); // 1
foo = function() {
console.log(2);
}
Notice that var foo was the duplicate (and thus ignored) declaration, even though it came before the function foo()... declaration, because function declarations are hoisted before normal variables.
While multiple/duplicate var declarations are effectively ignored, subsequent function declarations do override previous ones.
foo(); //3
function foo() {
? ?console.log(1);
}
foo = function() {
? ?console.log(2);
}
function foo() {
? ?console.log(3);
}
While this all may sound like nothing more than interesting academic trivia, it highlights the fact that duplicate definitions in the same scope are a really bad idea and will often lead to confusing results.
Reference from: YOU DON'T KNOW JS - SCOPE & CLOSURES