As a matter of fact it is, javascript is an interpreted language and the javascript interpreter performs a lot of mystical stuff behind the scenes. Hoisting in JavaScript is certainly one of them. A quick Google search shows, the term means to raise or haul up.
Something like this:
Think of the crane as the javascript interpreter here ð??? ð???
Think of variables and functions in javascript as a result of two small but important steps, declaration and initialization.
Declarations and Initializations:
1 2 3 | var sampleGlobalVar; //declaration sampleGlobalVar = 2; //initialization var sampleInitializedGlobalVar = 1; //declaration and initialization in one straight step |
In above piece of code,
1. The first line declares a variable called sampleGlobalVar.
2. The second line initializes or assigns the value to the variable sampleGlobalVar.
3. The third however, both declares and initializes the variables named sampleInitializedGlobalVar.
What we need to keep in mind is that variable declaration and initialization are always two different steps for the javascript interpreter. Even though we have the syntactic sugar to declare and initialize the variables in the same line, interpreter would still see it as a two step process identifying the declaration and initialization parts from the statement.
But you must ask,
What is hoisting in JavaScript?
Going by the definition, Hoisting is the process of moving the variable and function declarations to the top of their scope.Please note that we are referring here to the scope in which functions and variables are first declared which could be local or global.
You should also know that Javascript does not have block scopes
Resuming our discussion on hoisting, javascript interpreter would essentially be moving the declarations(always) to the top of the scopes in which they are declared.
For example: Assume we have this simple code in javascript,
1 2 3 4 5 6 7 8 9 | var sampleGlobalVar; sampleGlobalVar = 2; var sampleInitializedGlobalVar = 1; function xyz(){ console.log("Inside the function in javascript"); var sampleLocalVar = 3; console.log("local variable", sampleLocalVar); } |
What interpreter does is something like this and this is what you get from hoisting in JavaScript:
1 2 3 4 5 6 7 8 9 10 11 | var sampleGlobalVar; //declaration var sampleInitializedGlobalVar; //declaration hoisted sampleGlobalVar = 2; sampleInitializedGlobalVar = 1; //initialization essentially remains where it was function xyz(){ var sampleLocalVar; //declaration hoisted console.log("Inside the function in javascript"); sampleLocalVar = 3; console.log("local variable", sampleLocalVar); } |
But why is this important for us to understand? How does it matter to a developer if javascript interpreter performs hoisting.Let’s see that!
1 2 3 4 5 | var sampleVar = 4 function xyz(){ console.log("variable hoisting demo", sampleVar); var sampleVar = 8; } |
Output:
undefined
Surprised? Well, Don’t be!
Even though sampleVar has clearly been declared and initialized before trying to console its value inside the function xyz, it still outputs undefined.
First question: Why?
Hoisting.
Second question: How?
Shadowing.
Let’s see what is interpretor doing to our last piece of code: (This is an example of hoisting in JavaScript)
1 2 3 4 5 6 7 | var sampleVar; sampleVar = 4 function xyz(){ var sampleVar; console.log("variable hoisting demo", sampleVar); sampleVar = 8; } |
We are getting closer now. Javascript interpreter moved the sampleVar declaration to top of each of its scope.
Having sampleVar moved to the top of its global scope did not create any difference in this particular example, but hold on buddy! Keep going.
Hoisting of local sampleVar certainly did create a lot of difference because of Shadowing. Shadowing is yet another concept to understand here.
Since shadowing is responsible for “masking” the value of global variable if a variable with the same name has been defined “locally”, var sampleVar; (undefined only yet) here masks the global value 4 which is why we get undefined consoled out inside of the function.