HOISTING! Argh! Hoisting and Scope in JavaScript

Hoisting and scope, both words kind of remind me of pirates for some reason. Hoisting the main sail and looking for other ships to raid through the scope. Okay, so it’s a bit far-fetched. What does hoisting and scope really mean in context of JavaScript? Hopefully in this blog I can explain it in a way that both of us can understand.

Let’s talk about scope and where a variable is found within the code. Any variable declared outside of a function is considered to belong to the global scope and can be accessed from anywhere in the code. Every function has its own scope and a variable that is within that function cannot be accessed outside of that function. A nested function which is within a function can access that function’s variable. This would be called a local scope or function scope. One thing to note is that the JavaScript compiler looks from within the function for a variable and works out to the global scope if there is no variable within that local scope.

With a local variable declared with the same name as a global variable, the local variable will take precedence. This is an example of code to try out in the console:

var someVar = "I'm a global variable!";
function functionScope () {
var someVar = "I'm a local variable!";
console.log (someVar);
}
functionScope(); // output: I'm a local variable!
console.log (someVar); // output: I'm a global variable!

There are three variable keywords you can use for variables and they are ‘var’, ‘let’, and ‘const’. The syntax is the same for assigning a value to the keywords mentioned and naming the variable. For example, var car = “Audi”, would be a declaration of a variable using the var keyword. The variable name or identifier is car and “Audi”, this value (in this case a string) has been assigned to the variable car. For me, his has helped break down a declaration of a variable in small easy pieces. For ‘var’, it’s probably not a good idea to use especially in ES6 because it is a bit ‘wonky’ and will have unintentional results in your code. And yes, ‘wonky’ is my technical term.

Knowing this and the nature of each variable keywords, such as ‘var’, ‘let’, and ‘const’. The variable keyword ‘var’ has function scope, can be hoisted (explained later in this blog), can be reassigned and can be re-declared. The variable keyword ‘let’ has block scope, no hoisting, can be reassigned and cannot be re-declared. With ‘const’, it has block scope, no hoisting and cannot be reassigned or re-declared. It is best to use the ‘let’ keyword instead of ‘var’ in the ES6 because ‘let’ is a block scoped variable and it will prevent from unintentionally override variable values. Just keep these in mind as we go along in this blog.

Also to note that arrow functions are not quite the same as function declarations. Arrow functions are good for single line function expressions that can be ‘returned’. Arrow functions are always anonymous and are lexically scoped and have no ‘this’ only accessing the ‘this’ in the outer scope.

Now to go to what ‘hoisting’ means and how it works. Hoisting is not a pirate term in the JavaScript world. The W3Schools.com has a good definition of “Hoisting is JavaScript’s default behavior of moving declarations to the top.”

There are variable and function declarations and in the case of function declarations, the whole function is hoisted including the variable assignment and name. If a variable is outside of the function declaration, only the name of the variable is hoisted. Considering the code example above:

var someVar = "I'm a local variable!";

The ‘someVar’ gets hoisted and not the assignment of the string, “I’m a local variable!”

The most important thing to remember is to always declare your variables whether ‘var’, ‘let’ or ‘const’ and one variable statement per scope and it be at the top. This will prevent confusion in the hoisting process if you force yourself to keep this practice. Variable declarations are hoisted to the top of the containing scope. Also, variable initializations are not hoisted. For example:

var someVar; //is the declaration
someVar = “I’m a local variable!”; //is the initialization

JavaScript engines can come across a combination of declaration and initialization which splits automatically where the declaration gets hoisted and the initialization does not get hoisted. Function declarations override variable declarations, but not variable initializations. Another words, if there is a variable declared without initializing it with a value, the function declaration will take over with its own declaration. Function declarations are always hoisted, but function expressions are not hoisted. Examples below:

Function Declaration:
function functionName(arg1, arg2) {
// function body
}

Function Expression:
var functionName = function(arg1, arg2) {
// function body
}

Also since arrow functions are expressions, they not only don’t have ‘this’, there is no hoisting.

In the example below is where the function declaration overrides the variable declaration giving the function declaration priority:

function value() {
return 1;
}
var value;
console.log(typeof value); // function

function value() {
return 1;
}
var value = 1; // variable
console.log(typeof value); // number

This shows the variable initialization overrides the function declaration.

There is a lot to learn with scope and hoisting and it does take a bit (at least for me) to understand the concepts. Once it’s understood, it will make JavaScript a better language to have fun with and learn.

Leave a Reply

Your email address will not be published. Required fields are marked *