SoFunction
Updated on 2025-02-28

Detailed explanation of JavaScript advanced closures

1. The concept of closure

Let’s look at the execution and heuristics of general functions:

        function stop() {
            var num = 0;
            (num);
        }
        stop(); // Print out num is 0        (num); // Report an error Function not defined

1. At this time, the outside of the function cannot access the variables inside the function.

2. The variables defined inside the function will not always exist and disappear as the function runs.

Concept of closure:

1. It is a function that has permission to access variables in another scope.

2. Another way of saying that when the life cycle of an internal function is greater than the declaration cycle of an external function, and the internal function is accessed by an external scope in a certain way, a closure is generated.

Let’s see the following closure code and explanation:

        function fn() {
            var num = 10;
            // function fun() {
            //     (num);
 
            // }
            // return fun;
            return function () {
                (num); // 10
            }
        }
        var f = fn();
        f();

We can disassemble it into several parts:

1. The fn function has an internal return value and is a function.

2. The num variable is printed inside the return function. The reason why num variables can be printed is the access mechanism of the scope chain. The following will supplement the knowledge points of the scope and scope chain.

3. We use the f variable externally to accept fn(), that is, we accept the return value of fn [internal function]

4. Then call f, that is, call the internal function in fn. Finally able to print 10

Supplement to knowledge points:

1. Scope:

Variables work within a certain range, but outside this range, they do not work. This scope is the scope. Scope is generated when the function is defined, not when the function is called.

2. Scope chain:

In a sentence summary: According to [internal functions can access external function variables], the principle of proximity is adopted to search for variables layer by layer. This mechanism is called scope chain.

Function A contains function B, then function B is the internal function of function A.

If an internal function wants to use a variable, first look at whether there is this variable inside it.

If not, you will go to the next level to search, [Principle of proximity]

If the function cannot be found layer by layer, you will finally look for it under the global variable.

        var a = 1;
        var b = 11;
        function fn1() {
            var a = 2;
            var b = '22';
            fn2();
            function fn2() {
                var a = 3;
                fn3();
                function fn3() {
                    var a = 4;
                    (a); // 4
                    (b); // '22'
                }
            }
        }
        fn1();

3. Garbage recycling mechanism

You can refer to this brother's description of the JS garbage collection mechanism:

///article/

We combine these three concepts to see the role of closures

2. The function of closure:

We call function A an outer layer function, and there is a function B inside this function.

Use a variable f outside to accept the return value of function A [function B]

The variable in scope of function A is called num

1. Be able to access variables inside the function outside the function [build a channel for external access to internal scope]

principle: There is actually an explanation above.

First, we must understand the principle of the chain of action. Function B can call the variable num of function A

Secondly, we must understand that first, the return value of function A is function B [internal function], and secondly, this return value must be accepted by variable f outside the function. After acceptance, function B can be called, and function B will access the variable num of function A. And this internal function B is the closure function.

2. Can extend the life cycle of variables inside the function.

The first function brings the second effect. There is a garbage collection mechanism for js variables. If the function is executed, the variables will be cleared and the memory will be eliminated. However, if closures are used, the variables may not be cleared immediately.

The reason is that the external variable f accepts an internal function B of function A, and this internal function accesses the variable num in scope of function A. As long as function B executes and variable f always exists, the variable num will always exist. It will not disappear just because the execution of function A is finished.

I have referred to the following article, which is very detailed and recommended to read.

Detailed explanation of JavaScript closures

3. Closure example

Some applications of closures will be added later.

We need to remember when we use closures, and closures cannot be abused.

3.1 Click li to output the index number of the current li

    <ul class="nav">
        <li>durian</li>
        <li>Stinky tofu</li>
        <li>Canned herring</li>
        <li>Big pig's hoof</li>
    </ul>
    <script>
        // Closure application - Click on li to output the index number of the current li        // 1. We can use the method of dynamically adding attributes        var lis = ('.nav').querySelectorAll('li');
        for (var i = 0; i < ; i++) {
            lis[i].onclick = function () {
                (i); // Four 4            }
        }
    </script>

principle: If the picture above is written like this, the printed i will always be 4. The reason is that at this time, it is first in non-strict mode. In non-strict mode, the for loop executes tasks synchronously, and then clicking the button and then executing is an asynchronous task. After the synchronous execution is completed, i is added to 4. Then execute the asynchronous task and prints i, which are all 4.

Method 1: Use closure

Loop generates four immediate execution functions

2. Execute functions immediately is an application of closures. All functions in the function immediately, including the [Click Callback] function, can use the formal parameters passed by the function immediately.

        for (var i = 0; i < ; i++) {
            (function (i) {
                // (i);
                lis[i].onclick = function () {
                    (i);
 
                }
            })(i);
        }

Method 2: var--->let

Click the corresponding small li, and print i is the corresponding index number. Using let is ES6 syntax, at this time, for has a block-level scope

        var lis = ('.nav').querySelectorAll('li');
        for (let i = 0; i < ; i++) {
            lis[i].onclick = function () {
                // (i);
                (i);
            }
        }

Method 3: Use the method of setting custom attribute index

        var lis = ('.nav').querySelectorAll('li');
        for (var i = 0; i &lt; ; i++) { // Note that this is var, not let            lis[i].index = i; // Note that this is lis[i], there is no click at this time, where does this come from            lis[i].onclick = function () {
                ();
            }
        }

Summarize

That’s all for this article. I hope it can help you and I hope you can pay more attention to more of my content!