How Does JavaScript Works with Scopes, Hosting, and Closures?
Tags: javascript, codenewbie, beginners
Published: 2020-08-13 12:14:35

Scopes, Hoisting, and Closures are terms you will eventually have to deal with in your JavaScript codes. So, don't wait until you get an error you don't understand, and keep reading this post!

Before defining what is Hoisting and Closure, we first need to understand how scopes work in JavaScript.

# Scopes

If you google the [definition of "Scope"](https://www.google.com/search?q=scope+definition&rlz=1C1CHBF_esES908ES908&oq=scope+defin&aqs=chrome.0.0j69i57j0l6.3407j1j4&sourceid=chrome&ie=UTF-8) you will find that it is *"the extent of the area or subject matter that something deals with or to which it is relevant".* In simpler terms, a scope is an extent in which something is important. 

Talking in terms of JavaScript, the scope is the area in which variables and functions are accessible. There are two major scopes: Global and Local

## A) Global Scope

The global scope is the one where all other scopes can reach. Any variable or function declared in this scope, is accessible in any part of the code. Also, It is the first scope you can state variables and you can think of it as the father of all scopes. 

![First code](https://dev-to-uploads.s3.amazonaws.com/i/fhzeay942x0bbdsett3t.png)

In the above example, you can see that the `outerVariable` can be accessed inside the `foo()` function. Also, the variable is stated outside of any variable, so it is declared in the global scope. Also, the function `foo` is also declared on the global scope. So, you can access that function anywhere in your script. 

You realized that we thought of the inside of the function as another scope?

## B) Local Scope

There are different types of local scopes, exactly three types: **Function**, **Block**, and **Module**. 

### a) Function Scope

Every time you declare a function, it creates its scope. So, anything declared inside a function is only accessible inside the function. 

![Second Code](https://dev-to-uploads.s3.amazonaws.com/i/vavc5qtpzeou6n3o9b2h.png)

The `insiderVariable` does not belong to the Global Scope, so it can only be accessed in the scope of `foo()`

### b) Block Scope

In JavaScript, a group of statements arranged inside curly brackets ( **{}** ) is considered a block statement. These groups have their scope too. So, anything stated inside isn't available in outer scopes. 

![Third Code](https://dev-to-uploads.s3.amazonaws.com/i/9vsneton7le7yohmlu21.png)

Another example of a block scope are conditional statements:


![Fourth Code](https://dev-to-uploads.s3.amazonaws.com/i/8umd5te5wf21711idfjj.png)
 

### c) Module Scope

Any variable stated inside a JavaScript module can only be accessed inside it unless you export them. So every module has its scope too. 

For this example, first, we are going to create a module that exports a function 

![Sixth Code](https://dev-to-uploads.s3.amazonaws.com/i/kb2iuiqpp8mpu422kfeo.png)

Next, we are going to import this module inside our main JS and test the function

![Seventh Code](https://dev-to-uploads.s3.amazonaws.com/i/mp4rkt8xygcqel3xmf45.png)

As you can see, the function `sayHello()` can access the `str` variable because it belongs to the same scope but is not available in our importing module.

But we exported the function to our main JS, so now `sayHello()` belongs to this scope. Doesn't it seem weird that it can access the `str` constant?  

# Closures

Well, scopes are not the only reason why the function `sayHello()` can access the `str` variable, closures are involved too! 

In simple terms, closure is the capability that functions have in javascript to access the variables defined in the parent scope. This scope is bundled with the function. 

In the previous example, `sayHello()` can access `str` in another module because the variable is defined in the father scope and closures allow the function to access it.

Also, if you declare a function inside another one, the child can access the father function scope. 

![Eighth Code](https://dev-to-uploads.s3.amazonaws.com/i/o6cgagixpgqw1gu549bg.png)

# Hoisting

Now that you know about scopes, we can talk about Hoisting. It is the default behavior in which variable declarations are moved to the top of their scope. 

First, let's get clear that the only variables that are affected are the ones declared with `var` and with `function`. So, `const` and `let` are not affected by the hoisting.  Second, declaration and initialization are different steps.

![Ninth Code](https://dev-to-uploads.s3.amazonaws.com/i/k7lq3hx9d8opc6pqyqhe.png)

In order to understand this, let see this example:

![Tenth Code](https://dev-to-uploads.s3.amazonaws.com/i/5k3qq9adiy91n8jqroht.png)

The first time we execute `foo()` we should get a `ReferenceError`, instead, we are getting `undefined`. This is the magic of the hosting!

This is how the code would have look after the hoisting: 

![Whatever Code](https://dev-to-uploads.s3.amazonaws.com/i/7l3vy0llcb3018ocmimh.png)

As we said before, the declaration of the variable `a` is moved to the top of the scope, so when we first call the function `foo()` the variable has already been declared but not initialized, that why we get an `undefined`

Also, Hoisting is the reason why you can execute functions in the same scope before we have declared: 

![Eleventh Code](https://dev-to-uploads.s3.amazonaws.com/i/okz0n47ukr5jkd29zx68.png)

# Wrap-Up

- There are four different types of scopes:  **Global**, **Function**, **Block**, and **Module**.
- The difference between each scope is where you can access a variable in the script.
- The closure is the capability that functions have to access the variables stated in their parent scope.
- Hoisting is a default behavior where `var` and `function` declarations are moved to the top of their scope.

I recommend that you experiment with these concepts on your console to understand them better and if you have any questions ask me down on the comments section! 😬