Understand Scoping and Hoisting in JavaScript with Examples

0_tjdmu-HLub5mvJ_O.jpeg

JavaScript is weird, right? A lot of times, developers see an unexpected behavior in their code and they just want to tear their hair out. In this article, I am covering the two concepts that will help you understand those weird behaviors.

What is Scope?

Scope in JavaScript refers to the accessibility of variables, functions, and objects during runtime.

In JavaScript, there are three types of scopes:

  • Global Scope
  • Functional Scope
  • Block Scope

Global Scope:

Global scope is the outermost scope, a variable is in global scope if it’s declared outside of a block.

window and document are global variables provided by the browser.

1_AIazgVNQEoF1B5ktDbt-HA.png

Variable in Global Scope

Variables inside the global scope can be accessed and altered in any other scope.

Functional Scope:

Any variables or functions declared inside a function have local/functional scope, which means that they can be accessed within the function and not outside of it.

1_GAeJ2EyQShpiXbkgSlxg7g.png

Variable/Functions in a local scope

Block Scope:

Block scope tells us that any variable declared inside a block {}, can be accessed only inside that block and cannot be accessed outside of it.
Block scope is related to variables declared using let and const only, var do not have block scope.

Block statements like if and switch conditions or for and while loops create a block-level scope.

Hoisting:

When executing a JavaScript code, the JavaScript engine goes through two phases:

  • Parsing:- JS engine moves all the variable declarations to the top of the page if the variable is global otherwise at top of the function if declared within a function.
  • Execution:- JS engine assigns values to the variable and executes it.

So, hoisting is a mechanism that the JavaScript engine moves all the variables, functions declaration to the top of their scope, before the execution of the code. It allows functions and variables to be used in code before they are declared.

Take a look at the code below and guess what happens when we execute this:-

                console.log(data);
var data = 'hoist';
            

Every developer coming from any programming language will expect the output to be: ReferenceError: data is not defined, but instead, it will print undefined.

Why has this happened?

Just read the definition again about hoisting, JavaScript hoisted the variable declaration to the top of the scope, and this is what code looks like to the interpreter.

                var data;
console.log(data); // logs undefined
data = 'hoist';
            

Because of hoisting, we can use variables or functions before they are declared. Just remember hoisted variable is initialized with a value undefined.

Let’s take a deeper look at the variable and functional hoisting to understand how and what this means.

Variable Hoisting

In JavaScript, there are three different ways to declare a variable — var, let, and const. There are two steps: variable declarations and initialization.
JavaScript Interpreter only moves the declaration to the top of the code and not initialization.

Variable Hoisting acts differently depending on how the variable is declared. Let’s first understand var hoisting.

Var Hoisting

When JS interpreter hoist a variable declared with var, it initializes its value to undefined.

If we forgot the declaration and only initialize the value, the variable isn’t hoisted. Trying to read the variable before it is initialized and not hoisted will throw a ReferenceError exception.

However, initialization also causes declaration (if not already declared). The code below will work, as even though it isn’t hoisted, a variable is initialized and effectively declared before it is used.

By now, you all may be thinking, it’s kind of weird that JavaScript allows us to access variables before they’re declared. This is unusual from JS and can lead us to more confusion and lead to errors.
That’s why let and const were introduced in ECMAScript 2015.

let and const hoisting

Variable declared with let and const are hoisted but not initialized with a default value, unlike var. Trying to read the variable before it’s declared will be thrown an exception of ReferenceError.

Notice that the interpreter still hoists the variable ‘data’: the error message indicates that the variable is initialized somewhere.

As we have seen above, variables are hoisted to the top of their scope. Next, let’s look at how function scoped variables are hoisted.

Functional Hoisting

Function hoisting allows us to call a function before it is defined. Let’s take an example and try to guess the output

Following code runs successfully and outputs: ‘My cat’s name is Tiger’. Why?
Because function declarations are hoisted.

                Note: Only function declarations are hoisted, not function expression
            

This makes sense, as variable assignments aren’t hoisted. If we try to call the variable that the function expression was assigned to, we’ll get a TypeError or ReferenceError, depending on the variable’s scope.

Conclusion:

Let’s summarize this article:-

  • let and const are block scope whereas var is a global scope
  • var, let and const are all hoisted but unlike var, the other two are not initialized with a default value (undefined).
  • Function declarations are hoisted but not functional expressions

We should make it a habit to use let and const over var to avoid unnecessary errors.

Thanks for reading, I hoped you learn about scope and hoisting in JavaScript. Please share your views in the comment section, feedback is appreciated.
Check out my other articles on How to load scripts efficiently.
and Difference between map and forEach.


Only registered users can post comments. Please, login or signup.

Start blogging about your favorite technologies and get more readers

Join other developers and claim your FAUN account now!

Avatar

Ayush Tibra

@ayushtibra
Front-End Developer | ReactJS Developer
Stats
9

Influence

781

Total Hits

1

Posts

Discussed tools