Deep Diving into JavaScript Variables II
Tags: webdev, javascript, beginners, programming
Published: 2022-05-20 07:15:32

In the previous article, I explained about `scope` and the behaviour of declarations that are done using `var` keyword.

In this post, we will explore `let` and `const` declarations, their differences, and how they are better than `var`.

---
## CONTENTS
1. [let Keyword](#keyword-let)
   1. [Syntax](#syntax)
   1. [Scope of let](#scope-of-let)
   1. [let Declaration and the Global Object](#let-declaration-and-the-global-object)
   1. [let Declaration and Hoisting](#let-declaration-and-hoisting)
   1. [let and Redeclarations](#let-and-redeclarations)
1. [const Keyword](#keyword-const)
   1. [const Declaration Syntax](#const-declaration-syntax)
   1. [Scope of const](#scope-of-const)
   1. [const Declaration and the Global Object](#const-declaration-and-the-global-object)
   1. [const Declaration and hoisting](#const-declaration-and-hoisting)
   1. [const and Redeclarations](#const-and-redeclarations)

---

## Keyword let
- If you ever want a placeholder to hold values that changes over time, use `let`.
- While `var` is the black sheep, `let` is a beloved amongst the JavaScript family.
- `let` is stricter and more rigid than `var` in it's syntax rules and usage.

### Syntax
`let variableName [= value];`
- Variables declared with `let` have a block scope.
- What this means is that, if a variable using `let` is declared within a block, then it is accessible anywhere _only_ within that block and the sub-blocks.

### Scope of let
- We'll understand how the scope works using some examples
     ![block scope of let](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fawx6d4w8qwj36gnwfn8.png)

  - In the above example, the variable declared inside the test()  and the one declared within the if block are 2 different variables. That is their references (memory address) are different.
  - The output for the above code is -
  - ![block scope let output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a8p8hmvd9ruwwl5ndrlz.png)
  - Let me show you this through the console.
   ![let scope GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ow5ui50t7rysdlmmrcdl.gif)
  - Hence, any change made to the variable declared within the if block _does not reflect_ in the variable defined within the function. 

<br /> 
### let Declaration and the Global Object 
- Unlike `var`, `let` is not attached to the global object (or `globalThis`).
- This means that in any JavaScript environment, you ***cannot*** access a variable declared using `let` using the global object.

- e.g., in browsers, you have the global `window` and you cannot do the following- 
  - In the following example, where `x` is declared globally, you cannot use `window.x` to get the value of x.

![code for let global scoped](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2dnjfuv1fgj0pz9eh6p.png)
   
![let with global scope cannot be accessed via global object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvso214dzywfvnayf2a2.png)
 

- This is the reason variables declared using `let` are preferred over those declared with `var`. They provide a layer of protection and ensure that they remain local scoped.
   - If you see the scope tab in the console, you will find that the globally declared x appears under the `Script` scope.
      ![Scope of globally declared let](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u5s2ft227l3cncceyaqc.png)
 
### let Declaration and Hoisting
- Variable declarations using let ***ARE HOISTED***, but the hoisting works quite differently from variables that are hoisted when declared using using `var`. 
       ![code for let hoisting demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0wwex3xoqzhuhcimttc.png)
- If you run the above code, you'll get a `ReferenceError` that the variable cannot be accessed before initializing.
![Reference error when let declaration is accessed before initializing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhu69hbbh7u91hubt5r2.png)

> Note the error message could be different depending on the browser.

<br />
- But, we just saw that let declarations are hoisted. And in the case of `var`, the hoisted declarations were allocated memory prior to the code execution and also auto initialized to `undefined`. What about `let` declarations?
- Let us check if memory allocation and auto initialization happens with `let` declarations before code execution, on the chrome browser console.

<br />
![let hoisting console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9afy38pyqbrd2eads30p.png) 
- If I add a debugger on the first line in the above code and run, you'll see that in the scope tab, the `count` and `user` variables are allocated memory before the code execution and auto initialized to undefined. 
- Moreover, you will also see a detail that unlike the variable `admin`, the `count` variable has a scope `Script`. 
  - This shows that `let` variables are not part of the global object, they are allocated memory in a different scope (In this case `Script`). 

<br />
- As a rule, `let` declarations cannot be accessed before initializing and when you do so, you'll receive a ReferenceError.
- Now, a variable declared using `let` is said to be in the ***Temporal Dead Zone*** or ***TDZ*** from the time it was allocated memory to the time it is initialized.
- The below screenshot shows the TDZ time for the variable `count` for the above code.

![TDZ for the a variable declared using let](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4qsgy34xd1eo3ynlm5e8.png)
 

- So, when a variable is in it's TDZ, you cannot access it. If you do so, you'll get a `ReferenceError`.
- A variable in TDZ be like- ****Can't access***
![In the zone GIF](https://66.media.tumblr.com/3b24f6a0bd141a8cb3da917db251b41f/tumblr_o7uqqgfPJF1ufum4to2_250.gif)
<br />  

### let and Redeclarations
- You cannot re-declare a variable using let that was already declared with the same name within the same scope. If you do so, you will receive a SyntaxError. 
- Check out the code snippet below.
![Code snippet Redeclaration using let in the same scope](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/re9051qcwwb55pfpb8gh.png)
- Check out the output for the above code-
![Error for re declaration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q554hv5n5zptlfi4t2zh.png)
 
- You also cannot declare a variable using `let` that was previously declared using `var` with the same name and within the same scope. 


---

## Keyword const
- What if you have a value and you know that it's never going to change and will always remain the same?
- This is where a 3rd type of declaration comes in - constant declarations using keyword `const`.
- As the name suggests, `const` is used to declare constant values that will never change over time.

### const Declaration Syntax
`const variableName = value;`
- It is ***required*** to initialize a constant with a value during declaration.
- Variables declared with `const` also have a block scope.
- What this means is that, If a variable is declared using `const` within a block, then it is accessible anywhere _only_ within that block and the sub-blocks.
<br />

- Then what's the difference between let and const? The difference is that - 
  1. You cannot re-assign any values to a constant variable
  2. Constant variables need to be initialized when they are declared.

- The below code snippet shows how you declare a constant.
![constant declaration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nvjusgtgjjouuvkq3ley.png)
 
- Output for the above code -
![output for const declaration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/myjfmdxa5wmudk47eo9q.png)
 


- Like I mentioned above, you need to initialize a constant variable when you declare. If not you will receive a `SyntaxError` as shown in the screenshot for the below code snippet.
![Code snippet for declaration and then initializing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rotc8yx66yrdkhsjwhnv.png)
-Output for the code snippet above -
![Error when constants are not initialized during declaration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1pe381bsdry1z9audj4l.png)
 
 
 
 
### Scope of const
- The scope for `const` also works similar to the scope of `let`. 
     ![Scope of const](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a366v9qf7sn2jvo53b4g.png)
 
  
 
- Let us see the scope of the variable via console-
![Scope tab of const variable in the console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80cfxigsy3w56jrbloxl.png)
- As you can see, similar to declarations with `let`, globally defined constants are also allocated memory in the `Script` scope. 
 
- Let us look at another example. Let us trying a duplicate variable inside if() block and see what happens.
![Block scope of constant](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3u8t0bykvvugy8dw54f2.png)
 
- The output for the above code is -
![block scope of const output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53pwhcubg6y3zswro5hk.png)
- In the above example, the constant declared outside the if block and the one declared within the if block are 2 different constants. That is their references (memory address) are different.
  - Let me show you the scope of this constant through the console.
    ![const scope GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kows52uuc0gb2ib55j6g.gif)
  - Hence, any change made to the constant declared within the if block _does not reflect_ in the constant defined within the function.


### const Declaration and the Global Object 
- Similar to `let`, variables declared using `const` are not attached to the global object (or `globalThis`).
- This means that in any JavaScript environment, you ***cannot*** access a variable declared using `const` using the global object.

- e.g., in browsers, you have the global `window` and you cannot do the following- 
  - In the following example, where `x` is declared globally, you cannot use `window.x` to get the value of x.

![code for const globally scoped variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kx9qa1kfogbgbugcr9dd.png)
   
![const variable declared with global scope cannot be accessed via global object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ca0jomfvgo0xfmrusj89.png) 

### const Declaration and hoisting 
- Variable declarations using const ***ARE ALSO HOISTED***, and the hoisting works similarly to the variables that are hoisted when declared using using `let`. 
       ![code for const hoisting demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u46larqgv0u1xcdzhynf.png)
- If you run the above code, you'll get a `ReferenceError` that the variable cannot be accessed before initializing.
![Reference error when const declaration is accessed before initializing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6uurkato39p3kmikf745.png)
 
> Note the error message could be different depending on the browser. 

<br />
- Similar to `let` declarations, as a rule, `const` declarations cannot be accessed before initializing and when you do so, you'll receive a ReferenceError.
- The variable declared using `const is said to be in the ***Temporal Dead Zone*** or ***TDZ*** from the time it was allocated memory (from the beginning of it's scope) to the time it is initialized.
- The below screenshot shows the TDZ time for the variable `USER` for the above code.

![TDZ for the a variable declared using const](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2vldcl6ekjri941z9c5v.png) 

### const and Redeclarations
- You cannot re-declare a variable using const that was already declared with the same name within the _same scope_. If you do so, you will receive a SyntaxError. 
- Check out the code snippet below.
![Code snippet Redeclaration using const in the same scope](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j4cde833vm1h85wzeyqn.png)
 
- Check out the output for the above code-
![Error for const re declaration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7za8xj92madwyul8vm89.png)
 
 
- Just like let, you also cannot declare a variable using `const` that was previously declared using `var` with the same name and _within the same scope_. 
 
<hr />

## SUMMARY
That's all for this blog. Phew! Now, I know that this series was a lot, but then this is one of the most important concepts and is often asked in interviews.

To make things simpler, here's a flow chart citing the differences between `let`, `const`, and 'var` declarations.
![Differences Chart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dk3rfrzo72f1g4pkho3.png)
 

Thank you for sticking till the end.
Please do share if this helped you and also I would love to hear your thoughts!