Variables in JavaScript-Scope and Hoisting
Tags: javascript, beginners, webdev, programming
Published: 2022-02-10 08:30:02

##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:

```js
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:

```js
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:
```js
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:

- Functional Scope (function) for `var`
- Block Scope (condition or loop) for `let` and `const`

Take a look in below code:

```js
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;

- Trying to access a variable before it has been `declared` and `initialized`

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

- Trying to access a variable before it `initialized` without `declaring` it

```js
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.

```js
//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:

```js
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.

```js
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:

```js
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

- [Mozilla Docs](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
- [Digital Ocean Community](https://www.digitalocean.com/community/tutorials/understanding-variables-scope-hoisting-in-javascript)

## More on JavaScript
- [Data Types in JavaScript — The Weird Parts](https://withinbracket.com/posts/data-types-in-javascript-the-weird-parts/)
- [Type Conversion in JavaScript - The Magic](https://withinbracket.com/posts/type-conversion-in-javascript-the-magic/)
- [An Introduction to Loops in JavaScript](https://withinbracket.com/posts/loops-in-javascript/)
- [JavaScript Equality - Double Equals vs Triple Equals](https://withinbracket.com/posts/javascript-equality-double-equals-vs-triple-equals/)

Thanks for sticking around. Keep Learning.

📢**This article is officially been published on [Within Bracket](https://withinbracket.com)**.

📌Find more articles [Here](https://withinbracket.com/archives)