VAR, LET and CONST -Hoisting, and Scope
Tags: javascript, programming, softwaredevelopment, webdev
Published: 2019-08-29 16:05:30

---
title: VAR, LET and CONST -Hoisting, and Scope
published: true
cover_image: https://miro.medium.com/max/3200/1*k3cDk06MO3SFjgCUrC3ttg.jpeg
description: an in-depth explanation of the differences between the different methods of variable declarations in Javascript.
canonical_url: https://blog.usejournal.com/var-let-and-const-hoisting-and-scope-8860540031d1
tags: Javascript, Programming, Software Development, Web Development
---
***JavaScript***, like a lot of more modern languages, provides a host of different methods for variable declaration. JavaScript has the ***var***, ***let*** and ***const*** keywords for variable declarations and with each comes a different use case. This article aims to dive in-depth into the caveats and nuances which you might encounter when using either of these variable declaration methods.

For a bit more context, see the definitions of each of the keywords as defined in the [official ECMAScript specifications](https://www.ecma-international.org/ecma-262/6.0) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript).
> **Var** keyword declares a variable which is scoped to its current execution context, optionally initializing to a value.
> **Let** keyword declares a block-scoped variable, optionally initializing it to a value.
> **Const** keyword declares constants which are block scoped much like variables defined using **let** but the value of a constant cannot change. The **const** declaration creates a read-only reference to a value.

## HOISTING

Conceptually, hoisting suggests that variables and function declarations are physically moved to the top of your code. Technically, what happens is that the variable and function declarations are put into memory during the compilation phase but stay exactly where you typed them in your code. The primary importance of hoisting is that it allows you to use functions before you declare them in your code.

The key things to take out of the definition for hoisting are

* ***What gets moved around is variable and function declarations. Variable assignments or initialization are never moved around*.**

* ***The declarations are not exactly moved to the top of your code; instead, they are put into memory*.**

In JavaScript, all variables defined with the ***var*** keyword have an initial value of ***undefined***. This is due to hoisting which puts the variable declarations in memory and initializes them with the value of ***undefined***. This behavior can be shown with the following example

![line 2 throws a ReferenceError: y is not defined](https://cdn-images-1.medium.com/max/2000/1*LYZsYfSi_pNpUCHDo0z9lg.png)*line 2 throws a ReferenceError: y is not defined*

However, variables defined with ***let*** or ***const*** keywords when hoisted are not initialized with a value of ***undefined***. Rather, they are in a state called the **Temporal Dead Zone** and are not initialized until their definitions are evaluated.

![line 1 throws ReferenceError because it is still in Temporal Dead Zone](https://cdn-images-1.medium.com/max/2000/1*6_UuTjFttH5H_iuKttyeOg.png)*line 1 throws ReferenceError because it is still in Temporal Dead Zone*

The next code snippet demonstrates the hoisting of ***let*** and ***const*** variables.

![line 3 throws a ReferenceError because x in line 4 has been hoisted within the block](https://cdn-images-1.medium.com/max/2000/1*DpEAcywKXt-x_9rnueuwwQ.png)*line 3 throws a ReferenceError because x in line 4 has been hoisted within the block*

The ***x*** variable defined with ***let*** keyword in the block is hoisted and takes precedence over the ***x*** variable defined with ***var.*** However, it is still in the temporal dead zone when it’s referenced in ***console.log(x)*** and so throws a reference error.

## SCOPE

Variables defined with the ***var*** keyword have a scope that is its current execution context. They are not block scoped and so can be accessed from outside the block they were defined, provided it’s still within the scope of its execution context. ***Let*** and ***const*** variables, however, are block scoped and cannot be accessed from outside the block. This concept is shown below

![some variables are referenced outside of their scope](https://cdn-images-1.medium.com/max/2000/1*8BZU5l9Nq5Gs4DIKi0LFsw.png)*some variables are referenced outside of their scope*

Also, when you declare a global variable with ***var*** keyword, the variable gets attached to the global context (**window** in the browser and **global** in node). This is not the case with global variables declared with ***let*** and ***const***.

## GOTCHAS

* When you don’t declare a variable but assign a value to the variable, the variable gets created and is attached to the global execution context (***window*** in the browser and ***global*** in node). This, however, is strongly advised against as it makes debugging very difficult.

![the variables get attached to the global context](https://cdn-images-1.medium.com/max/2000/1*0QTwonrSzclzRSU8J5W7YQ.png)*the variables get attached to the global context*

* Variables declared with ***var*** keyword can be redeclared at any point in the code even within the same execution context. This is not the case for variables defined with ***let*** and ***const*** keywords as they can only be declared once within their lexical scope.

![cannot redeclare let and const variables.](https://cdn-images-1.medium.com/max/2000/1*OAzGqNuoFE6aO12c8LpKsw.png)*cannot redeclare let and const variables.*

This can especially cause a problem if you use ***let*** or ***const*** to declare a variable in multiple switch cases.

![foo in both cases reside in the same block scope](https://cdn-images-1.medium.com/max/2000/1*BS3MFChsa1IvKtX_0AQ4fQ.png)*foo in both cases reside in the same block scope*

Of course, it can be avoided by using curly braces around the cases to define different blocks, but this should probably be refactored.

![foo in both cases reside in different block scopes](https://cdn-images-1.medium.com/max/2000/1*srw2q2qH8ir8iwgOJy1YAw.png)*foo in both cases reside in different block scopes*

* Another gotcha to remember about constants is that even though its value cannot be reassigned to, it is still mutable. The behavior can be seen in the fact that if the value is an object, the object’s properties can be modified.

![variables defined with const are still mutable.](https://cdn-images-1.medium.com/max/2000/1*5GcP_6Bf3fzBBGcOcS9hxQ.png)*variables defined with const are still mutable.*

So yeah that pretty much sums up the definitions and gotchas with using either of the variable declaration methods.