Closure of advanced functions in Javascript

Understanding of closures

How to generate closures?

  • Closure occurs when a nested inner (child) function references a variable (function) of a nested outer (parent) function.

What is a closure?

  • Understanding 1: a closure is a nested internal function. For example, in the following example, the internal function fun2() is a closure
 function fun1(){
     var a = 'I am a variable defined by the parent element a';
     var b = 'variable b'
     function fun2 (){//fun2() is an internal function, a closure
         console.log(a);//Variable a declared in parent function is used
     }
     fun2();
 }
 fun1()//Call function fun1()

  • Understanding 2: through debug debugging, you can see that closures are objects containing variables (functions) of external functions referenced by internal functions.

  • From the mode, you can see that a Closure only displays variable a and no variable b. therefore, it can also be understood that a Closure is an object of a variable (function) of an external function referenced by an internal function.

  • Executing an internal function definition produces a closure (without calling the function)

Conditions for generating closures

  • Function nesting
  • The internal function references the data of the external function (variable / function)

Common closures

Take a function as the return value of another function

 function fun1() {
     var a = 0;
     function fun2() {
         a++;
         console.log(a);
     }
     return fun2;
 }
 var f = fun1();
 f();//1
 f();//2
 f();//3


be careful:

  • This process produces only one closure
  • Each call to f() is equivalent to one execution of fun2()

Pass a function as an argument to another function call

     function show(msg, time) {
         setTimeout(function () {
             console.log(msg);
         }, time)
     }
     show("Novelty time", 1000);
 </script>

Function of closure

  • Use variables inside the function to survive in memory after the function is executed (prolong the life cycle of local variables)
  • Data (variable / function) that can be manipulated (read and write) outside the function to the inside of the function

For example, in the above example

 function fun1() {
     var a = 0;
     function fun2() {
         a++;
         console.log(a);
     }
     return fun2;
 }
 var f = fun1();
 f();//1
 f();//2
 f();//3
  • In this example, variable a still exists in memory after the function is executed
  • You can operate (read and write) the variable a in fun1() through closures.

Closure lifecycle

  • Closure generation: a closure (not a call) is generated when the execution of the nested inner function definition is completed
  • Closure death: when nested inner functions become garbage objects
 function fun1() {
 //At this time, the closure has been generated (function promotion, internal function object has been established)
     var a = 0;
     function fun2() {
         a++;
         console.log(a);
     }
     return fun2;
 }
 var f = fun1();
 f();//1
 f();//2
 f();//3
 f = null;//Closure death (function objects containing closures become garbage objects)

Application of closures: defining JS modules

  • js files with specific functions
  • Encapsulate all data and functions inside a function (private)
  • Expose only one object and function containing n methods
  • The user of the module only needs to call the method through the exposed object of the module to realize the corresponding function

Custom module

  • Here, first create a JS file named myModule.js. The code is as follows
function myModule() {
    //Private data
    var str = "Hello  World!!!";
    //Functions that manipulate data
    function showBig() {
        console.log("showBig():" + str.toUpperCase());
    }
    function showSamll() {
        console.log("showSmall():" + str.toLowerCase());
    }
    //Exposed objects (Methods for external use)
    return {
        showBig: showBig,
        showSamll: showSamll
    }
}
  • Then, the myModule.js file is referenced in the html file through the < script > tag
    <script src="./myModule.js"></script>
    <script>
        var fn = myModule();
        fn.showBig();
        fn.showSmall();
    </script>

effect:

Another way of writing:
Add methods directly to the window by using the immediate execution function

(function() {
    //Private data
    var str = "Hello  World!!!";
    //Functions that manipulate data
    function showBig() {
        console.log("showBig():" + str.toUpperCase());
    }
    function showSmall() {
        console.log("showSmall():" + str.toLowerCase());
    }
    //Exposed objects (Methods for external use)
    window.myModule = {
        showBig: showBig,
        showSmall: showSmall
    }
})()
  • Then, the myModule.js file is referenced in the html file through the < script > tag
  <script src="./myModule.js"></script>
  <script>
      myModule.showBig();
      myModule.showSmall();
  </script>

Shortcomings and solutions of closures

shortcoming

  • After the function is executed, the local variables in the function are not released, and the memory consumption time will become longer
  • Easy to cause memory leakage

Memory overflow and leak

out of memory

  • An error in the operation of a program
  • When the program needs more memory than the remaining memory, a memory overflow error will be thrown

Memory leak

  • The occupied memory was not released in time
  • Excessive accumulation of memory leaks can easily lead to memory overflow

Common memory leaks

  • Unexpected global variables. There is no need to use var, let and const declarations. Variables are used directly
function fn(){
   a = new.Array(10000);
}
fn();
  • Timers or callback functions that are not cleaned up in time
  var time = setInterval(function(){//Do not clean after cycle timer
      console.log("Who else?");
  },1000);
  //clearInterval(time);
  • closure
 function fun1() {
     var a = 0;
     function fun2() {
         a++;
         console.log(a);
     }
     return fun2;
 }
 var f = fun1();
 f();//1
 f();//2
 f();//3 / / closures may cause memory leaks
 f = null;//Recycle closures -- > make internal functions garbage objects

resolvent

  • Use closures as little as possible
  • Timely release

Interview questions

Interview question 1

    //Code snippet 1
    var name = "The Window";
    var Object = {
        name: "The Object",
        getNameFunc: function () {
            return function () {
                return this.name;
            };
        }
    };
    console.log(Object.getNameFunc()());// ? "The Window"

    //Code snippet 2
    var name2 = "The Window";
    var Object = {
        name2: "The Object",
        getNameFunc: function () {
            var that = this;
            return function () {
                return that.name2;
            };
        }
    };
    console.log(Object.getNameFunc()());// ?  "The Object"

Resolution:

  • There is no closure in code fragment 1, which is equivalent to the direct execution of the function. Therefore, this points to The Window and prints "The Window"
  • In code fragment 2, the external function first declares that a variable saves this, and this points to Object, and then the internal function uses the external function variable that to generate a closure. The value in that saves The Object pointed to by this, so print "The Object"

Interview question 2

function fun(n, o){
    console.log(o);
    return{
        fun: function(m){
            return fun(m, n);
        }
    }
}

var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined, ?, ?, ? 
console.log("--------------------");
var b = fun(0).fun(1).fun(2).fun(3);//undefined, ?, ?, ?
console.log("--------------------");
var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined, ?, ?, ? 

thinking

  • First, find the variable that generates the closure, that is, n. each time you print the last generated closure, n. if no closure is generated, the print is undefined
  • As follows:
var a = fun(0); //undefined, a closure n = 0 will be generated here; Therefore, 0 will be printed below
a.fun(1); a.fun(2); a.fun(3);//0, 0, 0

console.log("--------------------");

var b = fun(0).fun(1).fun(2).fun(3);//undefined, 0, 1, 2

console.log("--------------------");
var c = fun(0).fun(1);//undefined, 0, closure n = 1 will be generated here;
	c.fun(2);//one 	 The closure n = 2 will be generated here, but it will be garbage collected
	c.fun(3);//one 	 The closure n = 3 will be generated here, but it will be garbage collected

Tags: Javascript Front-end ECMAScript

Posted on Mon, 29 Nov 2021 08:07:21 -0500 by demon_athens