DEV Community

Cover image for Understanding hoisting,scopes, and closures in JavaScript
Sam aghapour
Sam aghapour

Posted on

Understanding hoisting,scopes, and closures in JavaScript

hi everyone😀

there are a bunch of important concepts in javaScript that you should know as a JavaScript developer and today we’re gonna explore some of those concepts including “Scopes and closures and hoisting”.
I do my best to make it simple and as brief as possible, so let’s dive in.

1.Scopes **

what is scope anyway?
the scope is an area where variables, functions, and classes are accessible in.
scopes in javaScript
we have 2 types of scopes in JavaScript:

  1. Global Scope
  2. Local scope the variables that are declared inside a function are in the local scope (function scope) and the ones that are declared outside of a function are in the Global scope.

Global Scope
when you start declaring a variable outside of any function, it’s in Global scope and can be accessed everywhere (even in local scope) :

Image description

Local scope
when you declare a variable inside functions curly brackets, this variable is in Local scope and belongs to that area, it is not accessible outside of local scope (outside of the curly brackets including global scopes and other local scopes ) :

Image description

note there is an exception for this accessibility in other local scopes which we’ll talk about it.

Block Statement
there is something you should know and that is the “switch and if conditions”,” for and while loops” areas does not have a special local scope like functions and any variables declared inside these scopes are belong to and accessible in the scope which these loops or conditions are defined:

Image description
ECMAScript 2015(ES6) introduced two new keywords for declaring variables: let and const which have some differences from the var keyword and one of these differences that is good to be mentioned here is:
when we declare a variable with var keyword inside loops and condition curly brackets it’s accessible in the outer scope as we have seen before, but when declaring the variable with let or const keyword it is accessible inside that curly brackets and nowhere else! :

Image description

Lexical Scope
as I mentioned above, variables inside the local scope are just accessible inside that scope and not in the global scope or any other local scopes but there is an exception for this accessibility in other local scopes.
this exception belongs to this subject “The Lexical Scope (or Static Scope)”, but what is lexical scope?!
the lexical scope can be found in many programming languages and if I want to be brief: when we define a function inside a function, the inner function (or child function) has access to its parent function’s scope too, in another word if we have many nested functions, the child functions have access to their parent's scope too.

Image description
in the example above, you can see child function has access to all variables inside its parent's scope, and parent has access to grandfather’s scope but something interesting you may notice, is these accessibilities are top to bottom and parents can not have access to their children's scope.
so this is the Lexical Scope or Static Scope
Dynamic Scope
we have talked about static Scope, so it is not fair to leave Dynamic Scope behind without saying a word about it
I want to explain Dynamic scope with this example and compare it with static scope:

Image description

In the above example, there is an “a” function declared in the global scope and “b” function that includes ‘someVar’ variable with the value of 1 and a is invoked inside this local scope, and in global scope, we have the same someVar variable with different value of 0 and b is invoked, now what is gonna happen?is “a” function gonna log 0 as ‘someVar’ variable value? or 1?
well, that is the place that shows the differences between static and dynamic scopes.
in static scope: when “someVar” can’t be found in “a” local scope, javaScript is gonna look for it inside the scope that “a function has been declared “ it means global scope in this case and the value will be 0.
in dynamic scope: when “someVar” can’t be found in “a” local scope, javaScript is gonna look for it inside the scope that “a function has been invoked “ it means local scope (b function scope) in this case and the value will be 1.
summary of this comparison:

  1. in lexical scope it looks for missing variable in scope that the function has been declared.
  2. in dynamic scope it looks for missing variable in scope that the function has been invoked. it’s done! let’s go for closures🤠

2.Closures **

closure feature in js is about the capabilities of the inner function to accessing their parent functions scope which we already know some things about it, but the main usabilities of this feature have left.
thus, a closure is a function defined in other function scope and this closure function has access to three scopes (scope-chain):

  1. its own local scope
  2. its parents scopes
  3. the global scope

Image description
I’m sure you know that the inner function is the closure in the above example that is declared inside the outer function scope and besides its own ‘a’ variable, it has access to the ‘b’ variable of the outer scope.
note: variables lifespan inside a function scope begins when the function gets invoked and when the function execution gets finished, variables inside it are all gonna get cleaned like there was no variable like that.
so with this note let’s explore the above example step-by-step and see what is happening:

  1. function outer includes ‘b’ variable with the value of 50 and returns an inner function (note it returns function itself and not the function output)
  2. function inner is a closure and includes ‘a’ variable with the value of 30 and has access to ‘b’ variable and logs a + b (30+50).
  3. when we define x with outer(), now x is the same closure function and can be invoked:

Image description

  1. as soon as we define x = outer function, outer get execute and b variable inside it, is declared and after finishing the execution, b has been eliminated now, so when we call x(), how x is gonna find b value?
  2. when javaScript looks for ‘b’ and can't find it, there is just one thing that can rescue javaScript from this misery and that’s closure.
  3. inner goes to its parent scope and finds ‘b’ variable and remembers it, so when b was destroyed, it still remains in inner or x function and by calling x(), it will show us 80 (the result of a+b). ok, just one more important example to be sure you got this:

Image description

1.we defined x = NumberFunc , so NumberFunc get invoked and i variable is declared with the value of 0 , incrementNumberFunc (closure) is saved inside x variable and now x is equel to incrementNumberFunc function and NumberFunc has been finished and i variable destroyed , but i value(10) remains inside the closure

  1. the same thing is going with the ‘y’ variable
  2. when we call x() for the first time it gets executed and the ‘b’ variable is declared with the value of 10, it logs the ‘i’ variable which is remained as 0 and ‘b’ as 10, and then increase their value by ++, so ‘i’ variable remains in closure with the new value of 1 and finally b variable is destroyed (note b variable does not remain in closure).
    x(); //output : i = 0 , b = 10

  3. second time is the same process but the ‘i’ value remained as 1(because we increased its value ++ in the previous execution ) and the ‘b’ variable is still 10 and not 11, it is because it was destroyed in the previous execution and not saved in closure.
    x(); //output : i = 1 , b = 10

  4. the third time it is the same process as before
    x(); //output : i = 2 , b = 10

  5. finally we call y() and when we declared y it saved i with value 0 so the output:
    y(); //output : i = 0 , b = 10
    if we call y() again, it will increase the ‘i’ variable to 1.
    so, we learned closure is the combination of function and ability to remember outer scope or parent function scope variables.

3.hoisting **

hoisting is a mechanism in javaScript that takes our declared variables, functions, classes to the top of their scope without their defined value and gives them undefined value as default.
when we define a variable or function it has a lifecycle which is:

  1. Declaration: var i; 2.assignment/ initialisation: i = 20;
  2. usage: console.log(i + 22); we usually do it in one line: var i = 20; but it doesn’t matter how we do it, because javaScript declares it at the top and then assigns the value to it behind the scene before any code execution.

note: if you assign a value to undeclared variable, javaScript will declares it itself in the global scope and assigns the value to it. ☺ :

Image description
so now that we know how javaScript handles variables, it is recommended to declare and assign a variable before using it.
let me show you some examples that “what we see and what javaScript sees in our code “:
Global scope:
what we see:

Image description
what js sees:

Image description
Local scope:
what we see:

Image description
what js sees:

Image description
one of the other differences of let and const with the var keyword is :
in the situations that we saw above, the ‘let’ and ‘const’ keyword gets mad and won’t let you use variables before initializing it:

Image description
of course, you should know, if you declare a variable with an undefined value and give it a value after usage will not cause an error :

Image description
now let’s dive into other examples for functions and classes:

Functions:
we have two types of functions in js :
1.function declaration
function someFunc(){ //code }
in this type of function, javaScript take it to the top of its scope with its declared value (that is why we can use functions before declaring them):

Image description

2.function expression
var someFunc = function (){//code}
in this type, javaScript just take the declared name to the top with undefined value as default and not the given value and when we call the function before declaration it causes an error of “expression is not a function”, because it is not a function and it is an undefined:

Image description

classes:
we have two types of classes in js:
1.class declaration:
class SomeClass{
constructor(name, lasname) {
this.name= name; this.lastname= lastname;
}
}

in this type of class, javaScript is not gonna hoist it:

Image description

2.class expression:
var someClass = class{
constructor(name, lasname) {
this.name= name; this.lastname= lastname;
}
}

in this type, javaScript takes it to the top with undefined value as default, so it causes an error when we use it before assignment:

Image description

well, this article ends up here, I hope you learned something from it ☺
Goodbye and Good luck🤞

Top comments (0)