Understanding of js closure

Keywords: Javascript Attribute

Closure is a difficult and characteristic of javascript language. Many advanced applications rely on closures to implement. Personal understanding is: nested functions in functions.

The Definition of Closure and Its Advantages and Disadvantages

Closure is a function that has access to variables in the scope of another function. A common way to create closures is to create another function within one function.

The disadvantage of closures is resident memory, which will increase the amount of memory used, and improper use will lead to memory leaks.

Closures are used primarily to design private variables and methods.

Generally speaking, after the function is executed, the local active object will be destroyed, and only the global scope will be saved in memory, but the situation of closures is different!

Understanding closures requires understanding two other things: scope chains, garbage collection

Scope chain: When code is executed, a scope chain of variable objects is created. Scope chains are used to ensure orderly access to all variables and functions that the execution environment has access to.
See the following code:

//There is a variable color and a function changeColor() in the global environment.
 var color = "blue";
        //There is an anotherColor variable and swapColors() function in the local environment of changeColor().
        function changeColor() {
            var anotherColor = "red";
            //There is only one tempColor in the swapColors() environment
            function swapColors() {
                var tempColor = anotherColor;
                anotherColor = color;
                color = tempColor;
            }
            swapColors();
        }

        changeColor();

The global environment can only access the variable color
changeColor() Local environment can also access color
swapColors() can access all variables in the other two environments, but neither of them has access to tempColor

Summary: Internal environments can access all external environments through scope chains, but external environments cannot access any variables and functions in the internal environment. Each environment can search up the scope chain, but no environment can search down the scope chain and enter another execution environment.

Principle of garbage recovery

(1) If an object is no longer referenced in javascript, it will be recycled.
(2) If two objects refer to each other instead of being referenced by the third party, then the two objects that refer to each other will also be recycled.

Closure of nested functions

var f = function () {
            var a = 9999;
            function f1() {
                alert(a);
            }
            f1();
        };
        f();

When function nesting is completed, variable a will continue to be used by function f1, which is internally nested, so a will not be released. When the js parser finds that the function is nested, it saves the variables of the function and the variables of the sub-function together, forming a "closure". These variables will not be reclaimed by the memory reclaimer, and will only be reclaimed if the internally nested functions are not executed.

The characteristics of closures and the benefits of using them

Closures have three characteristics:
1. Nested function
2. External parameters and variables can be referenced within a function
3. Parameters and variables will not be recycled by garbage collection mechanism

The benefits of using closures:
1. Want a variable to reside in memory for a long time
2. Avoiding Global Variable Pollution
3. The existence of private member variables

Closure case

attribute

var person = function () {
            var name = "kimi";
            this.getName = function () {
                return name;
            };

        };
        var p = new person();
        alert(p.getName());

The name attribute is obtained through the getName method.

Find the index of the corresponding element directly in the loop

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" charset="UTF-8">
        window.onload = function () {
            var aLi = document.getElementsByTagName('li');
            for (var i = 0; i < aLi.length; i++) {
                aLi[i].onclick = function () {        //The for loop ends when clicked
                    alert(i);
                };
            }
        }
    </script>
</head>

<body>
    <ul>
        <li>a</li>
        <li>b</li>
        <li>c</li>
        <li>d</li>
    </ul>
</body>

</html>

Execution of the above code found that clicking on any one of the returned is 4, because when assigning value, passing i is a reference to memory address, the end of the loop, i is pointing to 4.

Rewrite the above code using closures

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>closure</title>
    <script type="text/javascript" charset="UTF-8">
        window.onload = function () {
            var aLi = document.getElementsByTagName('li');
            for (var i = 0; i < aLi.length; i++) {
                (function (i) {
                    aLi[i].onclick = function () {
                        alert(i);
                    };
                })(i);
            }
        };
    </script>
</head>

<body>
    <ul>
        <li>a</li>
        <li>b</li>
        <li>c</li>
        <li>d</li>
    </ul>
</body>

</html>

The current i is assigned by executing the function immediately at each iteration.

Accumulation of variables

Accumulation of Global Variables

 <script type="text/javascript" charset="UTF-8">
        var i = 1;
        function text() {
            i++;
            alert(i);
        }
        text();//2
        text();//3
    </script>

Accumulation of local variables

 <script type="text/javascript" charset="UTF-8">
        function text() {
            var i = 1;
            i++;
            alert(i);
        }
        text();//2
        text();//2
    </script>

The above code is not cumulative, rewrite the code as follows:

<script type="text/javascript" charset="UTF-8">
        function text() {
            var i = 1;
            return function () {//Function nesting
                i++;
                alert(i);
            }
        }
        var a = text();//External function assigns a
        a();//2
        a();//3
    </script>

Modular Code to Reduce Pollution of Global Variables

<script type="text/javascript" charset="UTF-8">
        var g = (function () {
            var i = 1;
            return function () {
                i++;
                alert(i);
            }
        })();
        g();//2 Calling g function once, actually calling the return value of the inner function inside.
        g();//3
    </script>

this object

Using this object in closures can cause some problems

<script type="text/javascript" charset="UTF-8">
        var name = "The Window";

        var object = {
            name: "My Object",

            getNameFunc: function () {
                return function () {
                    return this.name;
                };

            }

        };

        alert(object.getNameFunc()());//The Window
    </script>

The code first creates a global variable name, and then creates an object containing the name attribute. This object also contains a getNameFunc() method that returns an anonymous function, which in turn returns this.name. Calling object.getNameFunc()() returns a string. When searching for internal functions, only active objects are searched.

<script type="text/javascript" charset="UTF-8">
        var name = "The Window";

        var object = {
            name: "My Object",

            getNameFunc: function () {
                var that = this;
                return function () {
                    return that.name;
                };

            }

        };

        alert(object.getNameFunc()());//My Object
    </script>

Before defining anonymous functions, assign this object to that variable, which can also be accessed by closures. Even if the function returns, it still refers to object

After learning closures, I don't know where to use them or what to use them. Answer: (In fact, every js function you write is a closure, the top scope of a js function is a window object, and the execution environment of js itself is a scope (the global window/node of browser), which we usually call global scope. Each function, no matter how deep, can be considered as a sub-scope of the global scope and can be understood as a closure. )

This article is a summary of my own learning process. If there are any mistakes, please correct them.

Posted by jonabomer on Wed, 10 Jul 2019 14:11:34 -0700