JS Intermediate – What is Scope and Closure in Javascript

Home /

Table of Contents

Scope and Closure

Scope and closure are two important concepts in JavaScript that are closely related to each other. Scope refers to the accessibility of variables and functions in different parts of your code. In JavaScript, there are two types of scope: global and local. Global variables and functions can be accessed from anywhere in your code, while local variables and functions are only accessible within the block or function where they are declared.

Closure, on the other hand, refers to the ability of a function to access variables from its parent function, even after the parent function has finished executing. This is possible because the child function retains a reference to the parent function’s variables, which are stored in memory as part of the closure.

In practical terms, closures can be used to create private variables and functions in JavaScript, as well as to create functions that generate and return other functions. Closures are also useful for handling asynchronous operations and creating callbacks.

Understanding scope and closure is crucial for writing efficient and maintainable code in JavaScript. By carefully managing the scope of your variables and functions, and using closures to encapsulate and reuse code, you can create more robust and flexible applications that are easier to debug and maintain over time.

Hoisting

JavaScript Hoisting refers to the process where the interpreter causes function, variable, or class declarations to move to the top of their scope, before executing the code.

Hoisting allows functions to be safely used in code before they are declared.

Example:

abc()
 
function abc() {
   console.log('I am function');
}
newAbc()
 
var newAbc = function () {
   console.log('I am new Abc function');
}
newAbc()

Output:

I am function
/Projects/Enablegeek/hoisting.js:6
newAbc()
^

TypeError: newAbc is not a function

Note: Here the invoked newAbc function before declaring, will through an error because in the creational phase, newAbc remains undefined when it was invoked already.

Example:

abc()
 
function abc() {
   console.log('I am function');
}
var newAbc = function () {
   console.log('I am new Abc function');
}
newAbc()

Output:

I am function
I am new Abc function

Scope

The Scope determines where your declared variables or functions can be accessed or used. If you want to make a variable or function private or if you want to access a variable from anywhere, how or where to declare it is the topic of scope. Scopes can also be layered in a hierarchy, so that child scopes have access to parent scopes, but not vice versa.

JavaScript has the following kinds of scopes:

  • Global Scope: This is the default scope for all code running in the module
  • Module scope: The scope for code running in module mode.
  • Function scope: The scope is created with a function.
  • Block scope: When a scope created with a pair of curly braces is a block scope

Module scope and function scope is also known as local scope

Example:

var x = 345 // Global variable
 
function test() {
   var y = 678 // Local variable
   console.log('x and y : ', x,y); // x is accessible here
}
test()
console.log(y); // but the local variable y isn't accessible here.

Output:

Will through an error !!!

Automatically Global Variables

We can declare a variable in JavaScript without using the ‘var’ keyword. In that case, whatever scope this variable is in, it will automatically be treated as a global variable. The scope is determined in the creation phase, but the undeclared variable is executed upon arrival. And so it becomes a global variable.

Example:

function test() {
   name = 'Enablegeek'
}
test()
console.log(name);

Output:

Enablegeek

Lexical or Nested Scoping

Like a nested loop, there exists a nested function or nested scoping. A relationship between a parent function and a child function is created in lexical scoping. Now, what does “parent-child function” mean? Yes, if we declare another function inside a function, then the function inside which we declare the new function is the parent function. And any other function declared inside the parent function is a child function of that parent function. I hope the following example will clarify the idea.

function parentFunction() {
   // Some codes here
   function childFunction() {
       // Some codes here
   }
}

Now, here, parentFunction() is the global function, and childFunction() is the local function of parentFunction(). Now we know that variables, functions, or objects declared inside a function get the local scope and can be accessed only inside that function. But due to lexical scoping, anything locally declared inside parentFunction() can be accessed from inside parentFunction() and also from all its child functions. It can also be accessed from within the child function here.

Example:

function parentFunction() {
var a= 60
   function childFunction() {
       var b = 78
       console.log('Sum is: ', a+b);
   }
   childFunction()
}
parentFunction()

Output:

Sum is:  138

Closure

The closure is when a function is able to remember and access its lexical scope even when that function executes outside its lexical scope. A child function can always access the variable, function, or object of its parent function. But here is the more interesting thing: even if we return the parent function, we can still access the variable, function, or object of the parent function from the child function. because, after the function returns, they remain with the returned function. And that’s the closure. This is also javaScript’s default behavior, meaning we don’t have to code closures separately.

Example:

function test() {
   var msg = 'Relation between Lexical Scope and Closure'
 
   function sayMsg() {
       console.log(msg);
   }
   sayMsg()
}
 
test()

Output:

Relation between Lexical Scope and Closure
Share The Tutorial With Your Friends
Twiter
Facebook
LinkedIn
Email
WhatsApp
Skype
Reddit
Other Recommended Article