When it comes to closures in javascript, it’s important to understand why they exist and what they do. And why does a closure allow variables of an outer function to be kept all the time? We will analyze it from these two perspectives. Oh, yeah, sure. Detour. Thank you.

To get straight to the point, two core functions of closures are summarized:

  1. Read variables inside a function;
  2. Keep variables in memory at all times.

Read the variables inside the function

As we all know, variables have global variables and local variables in javascript. The internal function can access the external global variable, while the external function cannot access the internal local variable, which is a feature of JS:

var n = 999;
function f1() { console.log(n) } f1(); / / 999Copy the code

So the question is: how do you access variables inside a function from outside? One way to do this is to define a function inside the function and use this inner function to access the variables of the outer function, because the inner function belongs to the scope of the outer function (in accordance with the chain scope structure rules, children can find all the variables of the parent object level by level) :

funtion f1() {
    var n = 999;
    function f2() {
        console.log(n);
    }
    returnf2; } var result = f1(); result(); / / 999Copy the code

In this regard, Ruan Yifeng gave a popular explanation about closures: a closure is a function that can read the internal variables of other functions (there are different interpretations about whether the inner function is a closure or the outer function is a closure, but that’s not the point).

In JS, only subfunctions inside functions can read local variables, so it can also be understood as functions defined inside a function.

Keep variables in memory at all times

For the moment, a closure is a function that has access to a variable in the scope of another function. The function inside the function uses the variables of the outer function, making the variables of the outer function live longer, resulting in resident memory.

function foo(){
    var a = 2;
    return function(){ a += 1; console.log(a); } } var baz = foo(); baz(); // 3 baz(); // 4 baz(); // 5 baz(); / / 6Copy the code

Why is a not initialized each time baz is called in the above example? Next, consider the JS garbage collection mechanism.

1. Garbage collection mechanism

Usually, we can use reference counting method to determine whether a variable in your code is released, the language has a “reference list” in this engine, preserved the memory all the resources inside various value (usually) reference number, if a value reference number is 0, said the value is no longer used, therefore changes the value to be released in memory. Such as:

Cont arr = [1, 2, 3]; // Array [1,2,3] is a value that consumes memory and the variable arr is the only reference to this array, so the number of references is 1. Even though it's only assigned once and never called again in later code, it still takes up memory.Copy the code

High-level programming languages such as JS have embedded a mechanism called the garbage collector, whose job is to track the allocation and use of memory, so that any memory that is no longer needed can be found and released. Examples are as follows:

var o1 = { o2: { x: 1 } }; // Create 2 objects o2 and o1. O2 is referenced by o1 as its property, and there is no garbage to collect. O1 = 1; o1 = 1; o1 = 1; Var o4 = o3.o2; var o4 = o3.o2; var o4 = o3.o2; O4 = o4 = o4 = o4 = o4 = o4 = o4 = o4 = o4'666'; O4 = 16; o4 = 16; o4 = 16; o4 = 16; o4 = 16; // Now O2 can say goodbye...Copy the code

2. Explain memory reservation

Ok, now go back to the closure problem above and use garbage collection ideas to solve the problem:

function foo(){
    var a = 2;
    function outer() {
        a += 1;
	console.log(a);
    }
    returnouter } var baz = foo(); // Create variable baz in global scopeCopy the code

In this case, baz refers to outer, so outer is never destroyed. According to the garbage collection mechanism, a is not destroyed because there is a variable a in outer that refers to the outer function.

baz(); //3 baz(); //4 baz(); / / 5Copy the code

Is this clear? Let’s look at a simple classic example

3. Classic examples

Take a look at some of the classic interview questions and think of the results in terms of garbage collection, and you’ll be on your way:

var callbacks;
for(var i = 0 ; i <= 5 ; i ++) { callbacks =function() { console.log(i); } } callbacks(); //6 callbacks(); //6 callbacks(); / / 6Copy the code

reference

  1. Nguyen other teachers “learning Javascript closures” www.ruanyifeng.com/blog/2009/0…
  2. Reread JavaScript Advanced Programming reng99.cc/2018/03/01/…