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:
- Global Scope
- 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) :
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 ) :
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:
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! :
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.
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:
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:
- in lexical scope it looks for missing variable in scope that the function has been declared.
- 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):
- its own local scope
- its parents scopes
- the global scope
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:
- 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)
- 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).
- when we define x with outer(), now x is the same closure function and can be invoked:
- 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?
- 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.
- 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:
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
- the same thing is going with the âyâ variable
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
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 = 10the third time it is the same process as before
x(); //output : i = 2 , b = 10finally 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:
- Declaration:
var i;
2.assignment/ initialisation:i = 20;
- 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. âș :
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:
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:
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 :
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):
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:
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:
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:
well, this article ends up here, I hope you learned something from it âș
Goodbye and Good luckđ€
Top comments (0)