JavaScript Scopes & Closures: Simple Explanation To Developers


Introduction:
IIn the changing world of JavaScript, knowing about scopes and closures is crucial. In this blog, we'll explore these topics. First, we'll learn what scope is and the different types in JavaScript. Then, we'll look into closures. After reading this blog, you'll be able to master scopes and closures, helping you write clean code.
Scopes in JavaScript:
In javascript, Scopes refers to the lexical environment where a function or a variable is declared and accessed.
function fun1(){
function fun2(){
let a=0;
console.log(a);
}
fun2();
}
fun1();
In the example above, the variable a
is declared inside fun2
, and fun2
is declared inside fun1
. This means a
can only be accessed inside fun2
, and fun2
can only be accessed inside fun1
. Since fun1
is declared outside, its scope is global, meaning it can be accessed anywhere in the program. Variables declared inside a function can only be accessed within that function.
A lexical environment is a data structure that stores functions and variables in the call stack based on the current scope. It also contains references to the parent or outer scope. Whenever a function or variable is declared, it creates its own lexical environment.
Types of Scopes:
There are three types of scopes: Global, Local, and Block.
Global scope: Functions declared in the global scope can be accessed from any part of the program.
For example, in the code snippet below, the variable g
is declared globally, meaning outside of any function. Functions or variables declared in the global scope can be accessed at any level within any function.
let global_variable=5;
function parent(){
function child(){
let local = 10;
console.log(local);
console.log(global_variable); // prints the 5;
}
child();
}
parent();
Function Scope: Function or variable declared inside another function which is can accessed inside that function only. Like in the below example the parent function scope starts from the line we declared the parent() and ends where we close the parent function.
function parent(){
function child(){
let local =10;
console.log(local):
}
child();
//ends here.
}
console.log(local): // prints local variable is not declared
parent();
***Block Scope:***Any function or variable written inside the { } curly braces can only be accessed inside the curly braces only.
let x=5;
function parent(){
function child(){
let local=10;
console.log(local);
}
child();
}
console.log(local):// prints local variable is not declared
parent();
In the example above, the first block starts with the first {
curly brace and ends with the last }
curly brace. Anything declared inside this block can be accessed from the start to the end of these braces.Scopes of javascript variable depends on the position of declaration of variable:
var
variables act differently based on where they are declared. If you declare a variable outside a function, it is globally scoped. If you declare it inside a function, it is functionally scoped, as shown in the example below.
let x=5;
function parent(){
function child(){
var local=10;
console.log(local);
}
child();
}
console.log(local); // prints x is not defined
parent();
In the above example when we declare the the function the declared inside the child function it becomes functionally scoped and threw error when we tried to access it outside the function says x is not defined.
let x=5;
function parent(){
function child(){
var x=10;
console.log(x);
}
child();
}
console.log(x); // prints 10
parent();
But here, when we accessed it inside the function, it worked. We also declared it globally outside the parent function, so it can be used anywhere or at any deeper level. In ES6, let
and const
allow for block scoping, but var
is only functionally or globally scoped.
let a=5;
let x=10;
function parent(){
if(x===10){
let x=9;
}
console.log(x);
}
console.log(x); //prints 10;
parent();
In the above let keyword used for a variable is only be accessible inside that block.
Here is the example of const variable scope.
let a=5;
const x=10;
function parent(){
if(x===10){
const x=9;
}
console.log(x);
}
console.log(x); //prints 10
parent();
Closures:
Closures are a mechanism in JavaScript that combine functions and their lexical environment. When a function is enclosed inside another function, it creates a closure.
Closures allow access to their outer scope.
function parent(){
function child(){
let local=10;
console.log(local);
}
child();
}
parent();
In the code above, when we declare a child function, it creates a closure. This means the child can access the properties, variables, or functions of the parent function. If the parent function had another function above it as its parent, then the child function would also have access to its variables and functions, as shown in the screenshot below.
fucntion pparent(){
let p=10;
function parent(){
function child(){
let x=9;
cosole.log(p):
}
child();
}
parent();
}
pparent(); // prints 10
In javascript closures created everytime we creates a new function.
Using closures when we return a function inside another function it still maintains and remembers the variables and everthing which is inside that function as shown in below example
fucntion pparent(){
let p=10;
function parent(){
function child(){
let x=9;
cosole.log(p):
}
return child;
}
return parent;
}
const temp = pparent();
const tempchild = temp();
tempchild(); // prints 10
Above is another example of closures.
Conclusion:
In conclusion, understanding scopes and closures is key to writing clean and maintainable code. Scopes are determined by where a function is declared and include global, local, and block scope.
Closures are important when you want to return a function from another function while keeping access to its parent environments.
Subscribe to my newsletter
Read articles from Narendra Bhai Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
