Variable Hoisting and Scoping
Tags: javascript
Published: 2019-12-18 16:41:18

What is Hoisting in JavaScript?

Hoisting happens during the compile phase of a program execution. During this phase, the program is scanned and for variable and function declarations. They are all then added to a data structure called the Lexical Environment, where all of these declarations are stored in memory. Although it stores the declarations it doesn’t necessarily set the variable's value. Their values aren’t set until the engine reaches its actual initialization.  You can read more about hoisting [here](https://blog.bitsrc.io/hoisting-in-modern-javascript-let-const-and-var-b290405adfda).

```javascript
                     LexicalEnvironment = {
                        variableName:  <value>,
                        functionName:  <function object>
                     }
```

What is Scoping?

Scoping in JavaScript defines where variables can be accessible and visible from, it allows another part of the program to access them depending on where it is. There are three different types of scoping 1) Global 2) Block and 3) Function. You can learn more about scoping in this [article](https://blog.bitsrc.io/understanding-scope-and-scope-chain-in-javascript-f6637978cf53).

Hoisting and Scoping with ES6 JavaScript:

With the newest version of JavaScript, ES6, two new keywords were introduced to declare variables. We already had ‘var’ and now we have ‘let’ and ‘const’.

```javascript
                           var varName = 0;
                           let letName = 0;
                           const constName = 0;
```
 
‘var’ variable declarations:

When hoisting with a var variable, as explained above the program engine runs a scan for variable declarations. When it runs into a variable declaration with the keyword ‘var’ it will add it to the lexical environment and initialize it with a value of `undefined`. Later while the program is being executed it will reassign the variable to its actual value. 

```javascript
		      LexicalEnvironment = {
                         variableName:  <undefined>
                      }
```

Because var variables are being hoisted like this, you can access the variable before it has even been declared as long as it is being accessed from within its scope. 
Variables declared with `var` can only have a function scope or global scope. A function scope means that the variable can’t be accessed from outside the function it is declared in. If it is not declared inside a function then it has a global scope, which means it can be accessed from anywhere in the program. 

```javascript
                             //Global Scope:	
			  
                             var newNum=0;			     
                             function double(num){		       
                                newNum = num * 2;			      
                                return newNum;			     
                             }							 
                                          
                             console.log(newNum);			 
                             //will console log 0	                 
                             //assignment is being done 		 
                             //inside the function the 
                             //original Variable is 0

                            //Function Scope:

                            function double(num){
                              var newNum = num * 2;
                              return newNum;
                            }
                            console.log(newNum);
                            //will throw an error you
                            //can’t access the variable 
                            //outside the function
```



‘let’ and ‘const’ variable declarations:

When hoisting a variable with the keyword of ‘let’ or ‘const’ while the engine is scanning for variable declarations it saves them in the lexical environment but doesn’t initialize them at all. So if you are trying to access this variable even before it is declared, the program will throw a reference error. 

While ‘var’  variables have global and function scopes ‘let’ and ‘const’ variables only have block scopes, but can also have a global scope. Block scopes means that they are only accessible from within the block (curly brackets) where they are declared. If the variable isn’t declared within any pair of curly brackets, then it has a global scope and can be accessed from anywhere in the program. 

```javascript
                           //Block (Global) Scope:

//With "let" keyword
                           let newNum = 3;				
                           if (true){				
                             newNum *= 2;			    
                             console.log(newNum);		   
                           }					
 
                          //will console log 6,      	       
                          //since newNum has a global 		
                          //scope it can be accessed 		
                          //from within the function		

//With "const" keyword
                          const newName = 3;
                          function double(num){
                             return num * 2;	
                             console.log(newNum);
                          }
                         //will log 3, since it
                         //has a global scope
                         //it can be accessed 
                         //from within the function

                                //Block Scope:

                         if (true){				
                           let newNum = 3;			   
                           newNum *= 2;				  
                         }					
                         console.log(newNum);
			
                        //will throw a reference 		
                        //error since newNum isn’t		
                        //accessible from outside 		
                        //the block (if statement)		

                        if (true){
                          let newNum = 3;
                          newNum *= 2;	
                          console.log(newNum);
                        }

                        //will log 6  
                        //since newNum is 
                        //accessible from outside
                        //the pair of curly brackets
```