A rather unknown topic of Javascript is Hoisting. The Javascript compiler does not execute code as we write it. Hoisting is its way of re-arranging our code before executing it which is making declarations and taking it to the top of current scope. So, below code snippet:
function SumSquare(a, b) {
var x = add(a * a, b * b);
return x;
function add(c, d) {
var a = c + d;
return a;
}
}
Interpreted as:
function SumSquare(a, b) {
var x = undefined;
function add(c, d) {
var a = c + d;
return a;
}
x = add(a * a, b * b);
return x;
}
As we can see, JS did the following:
- Declared variables
- Hoisted declerations to the top of current scope
- Hoisted declared/named functions to the top
But same cannot be said for function assignments :
function Random() {
var random = function(){
return 10;
};
return random;
var random = function (){
return 9;
};
}
Will become:
function Random() {
var random = undefined; //will be overwritten by 2nd random
var random = undefined;
var random = function(){
return 10;
};
return random;
//unreachable
var random = function (){
return 9;
};
}
This is what happened:
- Function assignments did not get hoisted because assignments are not hoisted
- Variables with same identifier gets overwritten by the last one
- Second
random
function will not be reached because ofreturn
Lets go through another complex one for fun:
function theBridgeOfHoistingDoom() {
function fellowship() {
return "friends";
}
var sword = "sting";
var dwarf = function () {
return "axe";
};
var fall = "Fly you fools!";
fellowship = function () {
return "broken";
};
ring();
return sword;
fellowship = function () {
return "mines"
};
sword = function () {
return "glamdring";
};
var ring = function () {
return "precious";
};
}
Will become:
function theBridgeOfHoistingDoom() {
var sword = undefined;
var dwarf = undefined;
var fall = undefined;
var ring = undefined;
function fellowship(){
return "friends";
}
sword = "sting";
dwarf = function () {
return "axe";
};
fall = "Fly you fools!";
fellowship = function () {
return "broken";
};
ring();
return sword;
//unreachable
fellowship = function () {
return "mines"
};
sword = function () {
return "glamdring";
};
ring = function () {
return "precious";
};
}
Things happened above:
- Variable declarations
- Variables hoisted
- No declaration for
fellowship
because it was already named/declared function so it will just be overwritten/re-assigned.
At the time when I wrote this post back in 2015, ES6 was not around. But now in 2021, hoisting of var
is a thing of the past with addition of let
and const
in JS. Unlike var
which is function-scoped, let
and const
are block-scoped. They will be hoisted to the top of their immediate scope but unlike var
they won't be initialized with undefined
therefore, there will be a ReferenceError
instead of just outputting undefined
which is much more type-safe and predictable. Always prefer to use const
if not, then let
.