Divaksh
/Beginner’s Guide to Scope, Closures & Hoisting in JavaScript

Beginner’s Guide to Scope, Closures & Hoisting in JavaScript

Compiled on Jun 21 2021 in JavaScript

JavaScript has become one of the most widely used scripting language on the web. Before the epitome of JavaScript, webpages were not as interactive as they are today. JavaScript made web pages dynamic and enabled interactive features like animations and autoloading of the content. In this article, we will learn about the three chief concepts of JavaScript. Before going deep into these topics, let's learn some basics.

Scops in JavaScript

Scope refers to the limits the reach of variables, objects and functions and it defines the accessibility of the variables, objects, and functions. There are different types of scops in JavaScript.

Global Scope:

If a variable is declared outside of any function, then it is called the global variable. These types of variables are accessible throughout the code and from any function, that's why their scope is called global scope.

Local Scope:

If a variable is declared inside a function, then it is accessible only inside the function. Its value is independent from the value of the same variable outside the function. This means that these variables cannot be modified from outside the function. These variables are not accessible outside the scope of the function in which they are declared.

Block Scope:

Block scope means scope of those variables which are declared in between two curly brackets {} of conditional commands or loops. In JavaScript, variables can be defined such that their scope is limited to the part of the code between the curly brackets, then this is called block level scope. In such situations, variables are defined with let and const keywords. Whenever a variable is declared using let keyword then its scope automatically becomes the current block of code. If const keyword is used, then its value cannot be changed in any part of the code.

Lexical Scope:

Lexical scope simply covers that if a variable is defined in the parent scope then it is accessible in the child scope. Let's understand it with an example.

var outerFunction = function(){
    let outervariable = 'outervariable'
    var innerFunction = function(){
        console.log(outervariable);
    }
    innerFunction();
}
outerFunction();
//Output:
outervariable

In the above example, you can see that the 'outervariable' was defined in the parent scope of the innerFunction(), but it was accessible by the innerFunction() because of the lexical scoping. This does not mean that variables defined in the child scopes are accessible by the parent scope.

Closures in JavaScript

Now that we have an understanding of lexical scoping, we can start our journey to the closures. Closure is like an object which binds the variables under the lexical scope of a function to the function at the time of creation of closure.

In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

MDN Web Docs

Let's break the complexity with an example.

function bucket(){
   var item1 = 'book📕'
   var item2 = 'candy🍬'
   function printItems(){
           console.log(item1);
           console.log(item2);
   }
   return printItems();
}

var getInfo = bucket();

getInfo;
//Output:
book📕
candy🍬

In the above example, bucket() returns the printItems() to the variable 'getInfo'. Now we can easily see that getInfo variable is outside the child scope of the bucket(), but it can access its variables because of the closure that had bound the variables of bucket() to the printItems().

Why Closures are important

Use of the closures is to enable data privacy and create private variables. Using closure limits the scope of the variables inside a function. Variables of the outer function can be used through the inner function only; these variables are not accessible from any other part of the code.

What is Hoisting

Real life meaning of hoisting is to up-lift something and there is a similar context of it in JavaScript. In JavaScript hoisting refers to its mechanism of putting each declaration to the top of its scope in the code during execution and execute the declaration part first. It simply means that in JavaScript variables and functions can be used before their declaration. For better understanding of hoisting, we need to go through some basic terminologies. We must understand how JavaScript engine reads out the code. 

Execution Context

Execution context is a concept in JavaScript in which an environment is created where the entire code is evaluated and executed. During the execution context, the code is broken into smaller segments to make the execution process less complex. You can understand this by your own example. You also break the code into smaller sections while programming, so just like this JavaScript engine does. Execution context is done in two phases.

Global Execution Context

This execution context is created at the very first step and all the code which is not inside any function is becomes the part of global execution context. There are two objects gets created in the global execution context, a global window object and a variable called 'this'.

Global Object: Window

this: Window

Here 'this' variable is referring to the global object.

Creation Phase

In this part of execution, the JavaScript engine creates memory space for the variables and the functions for your code. All variable declarations get a default value 'undefined'.

var boy = Divaksh;
functon getName(){
     return boy;
}

For the above code, the creation phase will look like this:

Global Object: Window
this: Window
boy: undefined
getName: fn();

Execution Phase

In the Execution phase, the JavaScript engine runs each line of the code and assigns the values to the variables. Execution phase will look like this:

Global Object: Window
this: Window
boy: "Divaksh"
getName: fn();

Now let's combine all this and see what happens when the code is executed. Just look at the below code and guess what will be the output.

console.log(boy);
var boy = 'Divaksh';
Output: undefined

Let's Understand the Output:

Because during creation phase variable boy is given the value "undefined" and after that the console.log statement is encountered and hence the output is "undefined". This process of assigning "undefined" value to variable during creation phase is called Hoisting. JavaScript engine reads the above code like this:

var boy;
console.log(boy);
boy = 'Divaksh';

So that's why in JavaScript you can use initialize variables before declaring them and this rule also applies on function declarations. Let's understand this with an example:

snacks = 'chips';
getSnacks();
var snacks;
function getSnacks(){
return snacks;
}
Output: chips

Now we see that how JavaScript reads this code 

var snacks;
function getSnacks(){
return snacks;
}
snacks = chips;
getSnacks();

JavaScript has executed the variable and the function declaration part before the rest of the code. Isn't it interesting? Let me know in comments below.