JavaScript closures with Different Variables and Scopes

image

Are you more lost in JavaScript closures, Don't worry , In this article I will explain in the simplest way.

A closure is a function that has access to variables in its outer scope, even after the outer function has completed execution. Confusing 🤯 , Right ??

Child scope always has access of all data of parent scope(Inheritance Strategy) but not viceversa(If you are not familier with Scope Click here, I hope you will get a clear idea of js scope).

Here is the procedures, how closure works:

  • Compiler find variable's value in it's own scope , If available than it'd return the value.
  • If not found, compiler find the variable's value in parent scope, If available than it'd return the value.
  • If not available in parent scope, compiler find in GrandParent scope, If not found , this process goes on up to global scope.

Let try to understand from below example,

function outerFunction() {  let outerVariable = "I am in the outer function";  function innerFunction() {    console.log(outerVariable);  }  return innerFunction;}const inner = outerFunction();inner(); // Output: "I am in the outer function"

In this example, theouterFunction creates a variable called outerVariable and defines an inner function called innerFunction. innerFunction has access to outerVariable even though it's not defined within its own scope. When outerFunction is called and the innerFunction is returned and assigned to the inner variable, inner retains access to outerVariable through the closure created by outerFunction.

Here are a few more examples of closures with different variables and scopes:

Example 1:

Closures with local scope variables

function outerFunction() {  let outerVariable = "I am in the outer function";  function innerFunction() {    let innerVariable = "I am in the inner function";    console.log(`${outerVariable}, ${innerVariable}`);  }  return innerFunction;}const inner = outerFunction();inner(); // Output: "I am in the outer function, I am in the inner function"

In this example, outerFunction has a local variable called outerVariable, which is accessible to the inner function innerFunction. innerFunction also has a local variable called innerVariable, So compiler doesn't need to go on parent scope to get the value of innerVariable.

function outerFunction() {  let variable = "I am in the outer function";  function innerFunction() {    variable = "I am in the inner function";    console.log(variable);  }  return innerFunction;}const inner = outerFunction();inner(); // Output: "I am in the inner function"

In this example, outerFunction has a local variable called variable, which is accessible to the inner function innerFunction. But innerFunction also has a local variable called variable, So compiler doesn't need to go on parent scope to get the value of variable.

Example 2:

Closures with global scope variables

let globalVariable = "I am a global variable";function outerFunction() {  function innerFunction() {    console.log(globalVariable);  }  return innerFunction;}const inner = outerFunction();inner(); // Output: "I am a global variable"

In this example, globalVariable is defined outside of outerFunction and has global scope. innerFunction has access to globalVariable through the closure created by outerFunction.

Example 3:

Closures with arguments

function outerFunction(outerArg) {  function innerFunction(innerArg) {    console.log(`${outerArg}, ${innerArg}`);  }  return innerFunction;}const inner = outerFunction("I am an outer argument");inner("I am an inner argument"); // Output: "I am an outer argument, I am an inner argument"

In this example, outerFunction takes an argument outerArg and returns innerFunction, which takes an argument innerArg. innerFunction has access to outerArg through the closure created by outerFunction.

Conclusion

Get the value of a variable from it's most closest scope is known as closures. Closures are particularly useful for managing state in an application. By using closures, you can create functions that remember information about previous function calls, and use that information to make decisions about how to proceed in future function calls. This can be especially useful in cases where you need to maintain state across multiple function calls.

Thank you ☺️