What is a closure?

JavaScript closures are a feature. The official explanation is that a closure is an expression (usually a function) with many variables and the environment to which they are bound, and thus the variables are part of that expression. I believe there are many people do not understand this sentence. Let me express my understanding of JavaScript closures:

Examples of closures:

var count=10; Function add(){var count=0; Return function(){count+=1; // Inner scope of function alert(count); } } var s=add() s(); // output 1 s(); 2 / / outputCopy the code

The return value of add() is a function that executes the return of add() when s() is first called, which is the following function:

function(){ count+=1; // Inner scope of function alert(count); }Copy the code

So if we print count+1, where does count come from? According to the rule of scope chain, variables that are not declared at the bottom of the scope will be searched one level up, returned if they are found, kept looking until the variables of window are not returned, undefined if they are not. So obviously count is the internal count of flag2,

var count=10; Function add(){//var count=0; Return function(){count+=1; // Inner scope of function alert(count); } } var s=add() s(); // output 11 s(); / / output 12Copy the code

The first execution is unquestionable output 1. What about the second execution? Continue to execute the return method of that function, again count+=1; And then I print count, and that’s where the problem is, you don’t want to go up and find count=0; And then print 1? I don’t know if I noticed, but s of alpha performs the following function

function(){ count+=1; // Inner scope of function alert(count); }Copy the code

So add() is only executed once. Then s() is executed twice, and count is declared only once.

Var s=add(), the function add is only executed here once.

All of this is s(), so where did the second count come from? Yeah, it’s the same variable left over from the first add.

(How is this possible, function variables are released after execution, why is it still there? This is a reference counting problem for the garbage collection mechanism.

If a variable has a non-zero reference, it is not collected by garbage collection.

The first time s(),count is 1, and the second time s(),count is 2.

Let’s go back and see if we can change this function based on what we said above: if we execute add() twice, we should print 1

function add(){ var count=0; Return function(){count+=1; // Inner scope of function alert(count); } } add()(); // output 1 add()(); / / output 1Copy the code

And so it was. Both times the output is 1.

In addition, I think the closure said by Ruan Yifeng is also very simple: “My understanding is that a closure is a function that can read variables inside other functions.”

2 Scope of variables

To understand closures, you must first understand Javascript’s special variable scope.

There are only two types of scope for variables: global variables and local variables.

What makes the Javascript language special is that global variables can be read directly from inside functions.

Js code

var n=999;

The function f1 () {alert (n); }

f1(); / / 999

On the other hand, local variables within a function cannot naturally be read outside the function.

Js code

The function f1 () {var n = 999; }

alert(n); // error

One thing to note here is that when declaring variables inside a function, you must use the var command. If you don’t, you’re actually declaring a global variable!

Js code

() function f1 (n = 999; }

f1();

alert(n); / / 999

Sometimes you need to get a local variable inside a function, and inside a function, define a function.

Js code

function f1(){

n=999;

The function f2 () {alert (n); / / 999}

}

In the above code, the function f2 is included inside the function f1, and all local variables inside f1 are visible to F2. But the other way around, local variables inside F2 are invisible to F1. This is the Javascript language’s unique “chain scope” structure, in which child objects look up, level by level, to all the parent objects’ variables. Therefore, all variables of the parent object are visible to the child object, and vice versa.

Since F2 can read local variables in F1, it is possible to read its internal variables outside f1 simply by returning F2 as the value.

Js code

function f1(){

n=999;

The function f2 () {alert (n); }

return f2;

}

var result=f1();

result(); / / 999

3. Considerations for using closures

1) Because closures will cause variables in functions to be stored in memory, which consumes a lot of memory, so do not abuse closures, otherwise it will cause performance problems of web pages, and may lead to memory leaks in IE. The solution is to remove all unused local variables before exiting the function.

2) Closures change the values of variables inside the parent function outside the parent function. So be careful if you use a parent function as an object, a closure as its Public Method, and internal variables as its private values

Changes the value of a variable inside a parent function.

Use of closures

Closures can be used in many ways. It is useful for reading variables inside functions, as mentioned earlier, and for keeping their values in memory at all times.

How to understand this sentence? Look at the code below.

Js code

function f1(){

var n=999;

nAdd=function(){n+=1}

The function f2 () {alert (n); }

return f2;

}

var result=f1();

result(); / / 999

nAdd();

result(); / / 1000

In this code, result is actually the closure f2 function. It runs twice, the first with a value of 999 and the second with a value of 1000. This proves that the local variable n in function f1 is kept in memory and is not automatically cleared after f1 is called.

Why is that? The reason is that F1 is the parent of F2, and F2 is assigned to a global variable, which results in F2 always being in memory, and f2’s existence depends on F1, so F1 is always in memory and not collected by garbage collection when the call ends.

Another notable thing about this code is the line “nAdd=function(){n+=1}”. First, the var keyword is not used before nAdd, so nAdd is a global variable, not a local variable. Second, the value of nAdd is an anonymous function, and this

An anonymous function is itself a closure, so nAdd is a setter that operates outside the function on local variables inside the function.

5, conclusion

Understanding JavaScript closures is a necessary step toward becoming an advanced JS programmer. Understanding how they are interpreted and executed can lead to safer and more elegant code.