DEV Community

Cover image for How Does JavaScript Works with Scopes, Hosting, and Closures?
Maximiliano Hernández Betancourt
Maximiliano Hernández Betancourt

Posted on

How Does JavaScript Works with Scopes, Hosting, and Closures?

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" 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

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

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

Another example of a block scope are conditional statements:

Fourth Code

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

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

Seventh Code

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

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

In order to understand this, let see this example:

Tenth Code

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

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

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! 😬

Top comments (0)