A Quick Look Into JavaScript "Hoisting"
Tags: javascript
Published: 2019-12-11 00:07:04

JavaScript can be full of surprises with concepts that may not be quite obvious to many of us. In a couple of my previous posts, I have discussed a couple of them such as the use of "this" keyword and the differences and uses for the regular functions and arrow functions. In this post, I am going to continue the trend of exploring in the land of JavaScript with the concept that has caught me by surprised in the past, "Hoisting." Some of the JavaScript tests I took in the past introduced me to this particular subject and the answers to those questions were a little surprising to me so I have decided to dig into the mechanism of "hoisting" in JavaScript.

__Function Declaration__

Let's start with the definition of "hoisting." "Hoisting" is the behavior of moving all the declarations at the top of the scope before code execution according to GeeksforGeeks. This means that the functions or variables that are declared anywhere within the scope, local or global, will be moved to the top of the scope. One of the advantages of this mechanism is to be able to use a function before it is declared.
```
    sayName("John"); //My name is John
    
    function sayName(name) {

      console.log("My name is " + name);
    }
```
As demonstrated in the above code snippet that the function sayName can actually be called first and then declare later and the result will a string that gets print out with the name which is passed as a parameter to the function that gets appended to the string. However, the same effect might not be ideal for variable declarations. 

__Function Expression__ 

As mentioned earlier, function declarations are hoisted to the top of the scope but not function expressions. Function expressions are not hoisted to the top of the scope as demonstrated in the below code sample.
```
    hello(); //Uncaught TypeError: hello is not a function

    var hello = function() {
       console.log("Say hello!");
    } 

```
In the above code snippet, the variable hello is hoisted to the top but the function is not so when attempted to invoke the function hello, a type error is returned with a message stating that hello is not a function.

__"var"__

```
   console.log(name); //undefined

   var name = "John";
```
The above code snippet produces undefined when executed in browser console because the variable declaration actually gets moved above the line "console.log(name)." When the line "console.log(name)" gets executed, name hasn't been initialized so by default in JavaScript for variable declared with "var", it will be initialized with "undefined." Even though both declaration and initialization are written in one line, they are actually separated where the declaration part is getting "hoisted" to the top. Thus, the result undefined displays in the console. The above code snipped can be interpreted as below.
```
    var name; //declaration
    console.log(name); //undefined
    name = "John"; //initialization
```

__"let" and "const"__

I have used "var" when declaring variables in above examples for demonstrating "hoisting." There are also the "let" and "const" keywords for variable declarations, which are introduced in ES6, and are the variables declared with these two keywords getting "hoisted?" I have read somewhat conflicting information with regards to the use of "let" and "const" keywords and whether or not they are getting hoisted. Some strictly say they are not "hoisted" while others claim they are but in a different way.
```
    console.log(myName); //Uncaught ReferenceError: Cannot access 'myName' before initialization
    let myName = "John";
```
The above code snippet will produce a reference error because it's attempting to use a variable before it's initialized or assigned a value. Notice it says in the error message that "myName" cannot be accessed before initialization instead of flat out saying "myName" is not defined which means that myName is declared but hasn't been initialized. Unlike "var," the variables that are declared with "let" and "const" won't be initialized to undefined so a reference error is thrown. The above case makes me think that variables that are declared with "let" or "const" do get hoisted but have different behavior from that of "var."

__Conclusion__

"Hoisting" is another JavaScript concept that can be quite surprising for developers that are first starting out learning the language. The order of execution is quite different from other programming languages where the order of the lines pretty much determined the execution order. Due to the nature of "hoisting" that it is encouraged to declare and initialize functions and variables before using them to avoid unexpected outcomes. There are other nuances of "hoisting" that are not mentioned in this post but are presented in the resources below so if you want to learn more about them, they are pretty good references to dive into. 


__Referernces__
https://www.w3schools.com/js/js_hoisting.asp
https://scotch.io/tutorials/understanding-hoisting-in-javascript
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
https://www.geeksforgeeks.org/javascript-hoisting/
https://stackoverflow.com/questions/31219420/are-variables-declared-with-let-or-const-not-hoisted-in-es6