Variables in JavaScript, Scope and Hoisting

The core concept of programming, one should not skip.
Variables in JavaScript, Scope and Hoisting

Table of Contents

  1. Introduction
  2. How to use a Variable
  3. Scopes in JavaScript
  4. Hoisting in JavaScript
  5. More on Hoisting
  6. Conclusion

Introduction

Variables are the basic and a most important part of any programming language. They are used to store values that are used in the further execution of a program.

You can think variables like a box in which we can store something i.e., values.

In JavaScript variables can store any type of values. It can be a number, string, boolean, array, object, and what else. I don’t want to mess around with data types in this article, we discuss them in another one. Let’s keep our eye only one variable.

Let’s take a look how we use a variable in JavaScript:

    
        var x;            //Declare a variable
        x=10;             //Assign a value in it
        console.log(x);   //Use it
    

Before ES6 use var as variable keyword, but after ES6 there are two new keyword featured for assigning variable let and const.

But why let and const ?

To understand the importance of let and const, first we need to know two JavaScript features: Scoping and Hoisting

Let’s first discuss about Scoping:

Scoping simply means that at what range a variable can be accessed.

In JavaScript there are two type of scope: Global Scope and Local Scope

Didn’t get it ? Okay, don’t worry. Let’s do it practically. Consider following code:

    
        var global = 'i am a global variable';
        function doSomething() {                
            var local = 'i am a local variable';  
            console.log(local);                   
        }                                       
        console.log(global);
        console.log(local);
    

Output:

    
        i am a global variable
        ReferenceError: local is not defined
    

What’s is the ReferenceError ?

If you see in the above program, I declare two variables global and local.

The local variable is in the doSomething function, so you can’t access it outside the function. It means that the scope of variable local is within the function i.e, Local Scope.

But the variable global is declared outside of the function, so you can access it from anywhere. Thus variable global is in the Global Scope.

After ES6 the local scope is further divided into two part

  1. Functional Scope (function) for var
  2. Block Scope (condition or loop) for let and const

Take a look in below code:

    
        function doSomething() {
            if (1<2) {
                var cow = 'cow';
                let dog = 'dog';
                const cat = 'cat';
                console.log(cow);   //cow
                console.log(dog);   //dog
                console.log(cat);   //cat
            }
            console.log(cow);     //cow
            console.log(dog);     //ReferenceError: dog is not defined
            console.log(cat);     //ReferenceError: cat is not defined
        }
        doSomething();
    

As you can see if we try to access let and const variable outside of the if(block scope), it give a ReferenceError. However the var variable do its job perfectly within the function scope.

So that’s being said, the scope of var is functional scope where the scope of let and const is block scope.

Let’s first discuss about Hoisting:

When a variable or a function is declared, its declaration is moved to top of their scope.

Have a look at below condition;

1. Trying to access a variable before it has been declared and initialized

    
        console.log(name);  //access name before it defined or initialized
        var name='person';  //define and initialize after it been accessed
        /* Output */
        undefined
    

2. Trying to access a variable before it initialized without declaring it

    
        console.log(name);  //access name before it defined or initialized
        name='person';      //initialize name without it defined
        /* Output */
        ReferenceError: name is not defined
    

As we can see, if we access a variable before it has been declared and initialized, it return undefined. However if we access a variable before it initialized without declaring it, it returns a ReferenceError.

It’s seems ok in second condition that we not declared name before accessed it, so it gives a ReferenceError, but what happened in first condition is that JavaScript automatically declared the variable name before accessed it because we put a var keyword before the variable.

    
        //How we write it
        console.log(name);  //ReferenceError: name is not defined
        var name='person'; 

        //How JavaScirpt Manipulate it
        var name;
        console.log(name);  //undefined
        name='person';
    

Let’s see a big picture regarding hoisting:

    
        var statement = true;
        function checkHoisting() {
            //var statement;  /* Javascript automatically declared it here */
            if(1>2){
                var statement = false;
            }
            console.log(statement); // undefined
        }
        checkHoisting();
    

By seeing the example one can easily predict that the output should be true. But due to hoisting property JavaScript declared a new statement variable top on top of the checkHoisting function, which is not initialized, thus the output is undefined.

This type of output might cause a weird error.

But that simply not happen it case of let or const. Let’s see

    
        let statement = true;
        function checkHoisting() {
            if(1>2){
                let statement = false;
            }
            console.log(statement);   //the global statement variable
        }
        checkHoisting();

        //Output: true
    

let and const are not participate in hoist behavior, cause they are block-scoped variable.

Let’s have a look on another scenario:

    
        var statement = true;
        var statement = false;
        console.log(statement); // Output:false

        let done = true;
        let done = false;
        console.log(done);      
        //Output:SyntaxError: Identifier 'done' has     already been declared
    

What happened here ? Can you guess why ?

Let me simplify it.

When we declare a variable again with with a different value with var, then due to hoist behavior, the value of the variable updated with the latest value, thus the output is false.

But in case of let and const, as they not follow hoist property, it throw a SyntaxError that Identifier ‘done’ has already been declared.

This duplication of variable can also cause an error.

Conclusion

Due to scope and hoisting, the var keyword might cause an unpredictable result with w don’t want to occur. So as per the ES6 feature, it good to use let and const instead of var to keep our code less confusing and error free.

That’s being said, that all for this article. I hope this article might help you to understand the variable in JavaScript with scope and hoist property.

References

Thanks for sticking around. Keep Learning.