Unlocking the Power of JavaScript Closures

Unlocking the Power of JavaScript Closures

There are many different ways to explain the closure. I hope that the interpretation presented in this blog will be enough to deepen the understanding.

Retaining a link to variables or methods defined inside the function, after it has already been executed, is part of how a closure works. JavaScript is an ever-evolving language.

When closures came around, there were no classes or private variables in JavaScript. It can be said that until EcmaScript 6, closures could be used to (roughly) simulate something similar to what is known as object’s method privacy.

Closures are part of the traditional programming style in JavaScript.


What Is Closure?

A closure retains the values of local variables from a function after it has finished executing. Understanding closures can be challenging without knowledge of scope rules and how execution context controls the flow in JavaScript.

However, we can simplify this task by examining a few practical examples. To grasp closures, it is essential to comprehend the concept of defining a function within another function in JavaScript, as this is the core idea behind closures.

A closure in JavaScript allows variables and functions defined inside a function to remain in memory even after the function is called. This can be used to retain a link to those variables or methods. Closures were used to simulate object method privacy before the introduction of classes and private variables in ECMAScript 6. To understand closures, it is important to understand the concept of defining a function inside another function.

// The following global() is defined in an already existing 
// execution context that was created together with window
function global(){ 
// At the time global() is invoked, a new execution 
// context wil be created for this function scope. 
// During declaration binding instantiation, internal 
// to JavaScript interpreter, inner() will be created 
// as a new natgive object with a scope that points to 
// variable environment of global()'s execution context 
function inner(){ 
    console.log("inner"); 
} 
inner(); // Call inner 
}
global(); // "inner"

In the following example, the global function sendEmail defines an anonymous function and assigns it to the variable sendEmail. This variable is visible only from the scope of sendEmail function, but not from global scope:

function sendEmail(from, sub, message){
    let msg = `"${sub}" > "${message}" received from ${from}.`;
    let send = function(){ console.log(msg); }
    send();
}
sendEmail('John','Re:subject','Good news.');

In JavaScript, inner functions have access to variables defined in the scope of the function in which they are defined.

When we call sendEmail will create and call send function. It is not possible to call send () directly from the global scope.

Console Output :

“Re: subject“ > “Good news.” received from John.

We can expose a reference to private methods (inner functions) by returning them from the function. The following example is the same as the one above, except here instead of calling the send method we return a reference to it.

function sendEmail(from, sub, message){
    let msg = `"${sub}" > "${message}" received from ${from}.`;
    let send = function(){ console.log(msg); }
    return send();
}

// Create a reference to sendMail
let ref = sendEmail('John','Re:subject','Good news.');

// Call by reference name
ref();

Instead of calling send(), let’s return it. This way a reference to this private method can be created in the global scope.

Now we can call send() by reference directly from the global scope.

Even after sendEmail function was called, msg and send variables remained in memory. In languages like C, they would be removed from the automatic memory on
the stack, and we wouldn’t be able to access them. But not in JavaScript.


Beautiful Closure

It can be assumed that closure is used in Functional Programming for similar reasons to why private methods are used in Object Oriented Programming. They provide a method API to an object in the form of a function.

What if we could advance this idea and create a closure that looked beautiful and returned several methods rather than just one?

let get = null; //placholder for global getter function
function closure(){
    this.inc = 0;
    get = () => this.inc; //getter

    function increase() { this.inc++; }
    function decrease() { this.inc--; }
    function set(v) { this.inc = v; }
    function reset() { this.inc = 0; }
    function del() {
        delete this.inc; // becomes undefined
        this.inc = null; // additionally rest it to null
        console.log("this.inc deleted");
    }
    function reAdd(){
        //if null or undefined
        if(!this.inc)
        this.inc = "re-added";
    }
    // Return all methods at once
    return [increase, decrease, set, reset, del, readd];    
}

The del method will completely remove the inc property from the object and reAdd will re-add the property back. For simplicity of the explanation, there is no safeguarding against errors. But naturally, if the inc property was deleted, and an attempt to call any of the methods was detected, a reference error would be generated.

Initialize closure:

let f = closure();

Variable f now points to an array of exposed methods. We can bring them into global scope by assigning teams to unique function names:

let inc = f[0];
let dec = f[1];
let set = f[2];
let res = f[3];
let del = f[4];
let add = f[5];

We can now call them to modify the hidden inc property,

inc(); //1
inc(); //2
inc(); //3
dec(); //2
get(); //2
set(7); //7
get(); //7
res(0); //0
get(); //0

Conclusion

In JavaScript, closures are created when a function is declared inside another function. This allows the inner function to retain references to the local variables of its parent function, even after the parent function has finished executing.

Closures are powerful because they preserve the state of variables, keeping them accessible and unaltered. By creating a reference to the variables in the global scope or returning the closure, we can maintain access to them.

However, the new Function() constructor does not create a closure. Closures in JavaScript provide a way to create flexible and powerful code structures.

I hope this information was helpful 😊. Please feel free to ask me any other questions you may have. I am always happy to help 🤗.