Understand Javascript closures

  • 2020-03-26 21:46:49
  • OfStack

Closures are an important feature of ECMAScript, but they are difficult to describe in a proper definition. Although closures are difficult to describe clearly, they are easy to create, or, in other words, accidentally create. However, there are some potential problems with the existence of closures. In order to avoid creating closures "accidentally" and to take better advantage of closures, it is necessary to understand the mechanism of closures.

The definition of a closure
 
There are too many definitions of closures, especially some that are very abstract, like this one:

A "closure" is an expression (typically A function) that can have free variables together with an environment that binds those variables.

Basically, a closure is an expression that has some free variables and an execution environment that binds those variables. This definition is too literal to understand.

There is another definition:
All functions are closures. This definition confuses me; in other words, since Javascript has no block-level scope, closures generally refer to functions (I can't think of any other way to construct closures other than functions).

Rather than talk too much about functions and closures, here's what I think is an easy definition to follow.

First, closures exist based on scoped chains. Because of the scope chain, all functions, even global ones, can refer to variables (free variables) in the context of execution.

Second, there must be free variables inside a closure. By the way, there are two variables: 1. Local variables (bound variables) and 2. Non-local variables (free variables).

Finally, it still exists after the end of its context. The inner function has a longer lifetime than its outer function.

 
Resolution of closure definitions
 
With respect to the definition of a closure, we have been considering whether we must satisfy both.

First, if a closure does not have free variables inside, that is, it does not access external variables, then it loses its meaning. (unless the behavior is changed through other closures) so I think free variables is a requirement.

Second, if there are free variables inside a function, it will be destroyed when its context is destroyed. You can imagine an internal function that accesses its external function variables but then recycles them when the external function is finished executing. In this case, the discussion of closures is meaningless.

 
Here are two examples:


var objectA = (function() {
        var localA = "localA";

        innerFn();
              //Pure inner function call
        function innerFn() {
            localA = "innerChange";
        }

        return {
            getLocalA : function() {
                return "empty";
            }
        };
    })();

    objectA.getLocalA();

    objectA.getLocalA = function() {
        return localA;
    };

    //console.log(objectA.getLocalA()); //error: localA is not defined

 
    var objectB = (function() {
        var localB = "localB";

        return {
            getLocalB : function() {
                return "empty";
            },

            updateGetLocalB : function() {
                this.getLocalB = function() {
                    return localB;
                };
            },

            updateLocalB : function() {
                localB = "changeLocalB";
            }
        };
    })();

    console.log(objectB.getLocalB()); // empty
       //Change through other closures
    objectB.updateGetLocalB();

    console.log(objectB.getLocalB()); // localB

    objectB.updateLocalB();

    console.log(objectB.getLocalB()); // changeLocalB

The advantages and disadvantages of closures

The advantage of closures is that they have internal access to the arguments and variables of the external functions that define them (except for this and arguments).
The main problem with closures is that they hold the scope of the functions that contain them, and therefore take up more memory than normal functions, so they should not be overused.

Application of closures

The most basic application scenario for closures is to achieve privacy by protecting internal variables, such as module patterns.


Related articles: