Javascript: a deep understanding of js closures

Source: Internet
Author: User
Tags javascript closure example
Closure is a difficult and characteristic of Javascript language. Many advanced applications rely on closures for implementation. 1. To understand the scope of variables, you must first understand the special scope of variables in Javascript. Variables have two scopes: global variables and local variables... SyntaxHighlighter. all ();

Closure is a difficult and characteristic of Javascript language. Many advanced applications rely on closures for implementation.
I. Scope of Variables
 
To understand closures, you must first understand the special variable scopes of Javascript.
Variables have two scopes: global variables and local variables.
The special feature of Javascript is that the function can directly read global variables.

Js Code
Var n = 999;
Function f1 (){
Alert (n );
}
F1 (); // 999.
On the other hand, local variables in the function cannot be read outside the function.
Js Code
Function f1 (){
Var n = 999;
}
Alert (n); // error
Note that you must use the var command when declaring variables in a function. If you don't need it, you actually declare a global variable!
Js Code
Function f1 (){
N = 999;
}
F1 ();
Alert (n); // 999
Bytes --------------------------------------------------------------------------------------------------------
2. How to read local variables from the outside?
For various reasons, we sometimes need to get local variables in the function. However, as we have already said, under normal circumstances, this cannot be done. It can only be implemented through a work und.
That is to define another function within the function.
Js Code
Function f1 (){
N = 999;
Function f2 (){
Alert (n); // 999
}
}
In the code above, function f2 is included in function f1. All local variables in function f1 are visible to f2. But in turn, the local variables in f2 are invisible to f1. This is the unique "chain scope" structure of Javascript language ),
The sub-object looks up for the variables of all parent objects at a level. Therefore, all variables of the parent object are visible to the child object, and vice versa.
Since f2 can read local variables in f1, As long as f2 is taken as the return value, we can't read its internal variables outside f1!

Js Code
Function f1 (){
N = 999;
Function f2 (){
Alert (n );
}
Return f2;
}
Var result = f1 ();
Result (); // 999.
Bytes --------------------------------------------------------------------------------------------------------
Iii. Concepts of closures
The f2 function in the previous code is the closure.
Closure definitions in various professional documents are very abstract and hard to understand. In my understanding, closures are functions that can read internal variables of other functions.
In Javascript, only the subfunctions in a function can read local variables. Therefore, you can simply understand the closure as a function defined in a function ".
Therefore, in essence, closure is a bridge connecting the internal and external functions of a function.
Limit B
Iv. Use of closures
Closures can be used in many places. It has two major functions: one is to read the internal variables of the function mentioned above, and the other is to keep the values of these variables in the memory.
How can we understand this sentence? See the following code.

Js Code
Function f1 (){
Var n = 999;
NAdd = function () {n + = 1}
Function f2 (){
Alert (n );
}
Return f2;
}
Var result = f1 ();
Result (); // 999.
NAdd ();
Result (); // 1000.
In this Code, the result is actually the f2 function of the closure. It runs twice in total. The first value is 999, and the second value is 1000. This proves that the local variable n in function f1 has been stored in the memory and is not automatically cleared after f1 is called.
Why? The reason is that f1 is the parent function of f2, and f2 is assigned a global variable, which causes f2 to always be in the memory, while f2 depends on f1, therefore, f1 is always in the memory and will not be recycled by the garbage collection mechanism after the call is completed.
Another noteworthy part of this Code is the line "nAdd = function () {n + = 1}". The var keyword is not used before nAdd, therefore, nAdd is a global variable rather than a local variable. Secondly, the value of nAdd is an anonymous function.
The anonymous function itself is also a closure, so nAdd is equivalent to a setter. You can operate on local variables inside the function outside the function.
Bytes --------------------------------------------------------------------------------------------------------
5. Notes on using closures
1) because the closure will make the variables in the function be stored in the memory, the memory consumption is very large, so the closure cannot be abused, otherwise it will cause the performance of the web page, memory leakage may occur in IE. The solution is to delete all unused local variables before exiting the function.
2) The closure changes the value of the internal variable of the parent function outside the parent function. Therefore, if you use the parent function as an object, use the closure as its Public Method, and use internal variables as its private value ), be sure to be careful.
Change the value of the internal variable of the parent function.
Bytes --------------------------------------------------------------------------------------------------------
Vi. Questions
If you can understand the running results of the following code, you should understand the operating mechanism of the closure.
Js Code
Var name = "The Window ";
Var object = {
Name: "My Object ",
GetNameFunc: function (){
Return function (){
Return this. name;
};
}
};
Alert (object. getNameFunc (); // The Window
Bytes --------------------------------------------------------------------------------------------------------
JavaScript closure example
Function outerFun ()
{
Var a = 0;
Function innerFun ()
{
A ++;
Alert ();
}
}
InnerFun ()
The above code is wrong. innerFun () is in the scope of outerFun (), and it is wrong to call it outside outerFun.
Change it to the following, that is, the closure:
Js Code
Function outerFun ()
{
Var a = 0;
Function innerFun ()
{
A ++;
Alert ();
}
Return innerFun; // note the following:
}
Var obj = outerFun ();
Obj (); // The result is 1.
Obj (); // The result is 2.
Var obj2 = outerFun ();
Obj2 (); // The result is 1.
Obj2 (); // The result is 2.
What is a closure:
When an internal function defines its external scope as being referenced, it creates a closure for the internal function. If the internal function references a variable in the external function, after an external function is called, these variables will not be released in the memory because the closure needs them.
Bytes --------------------------------------------------------------------------------------------------------
Let's look at an example.
Js Code
Function outerFun ()
{
Var a = 0;
Alert ();
}
Var a = 4;
OuterFun ();
Alert ();
The result is. Because the var keyword is used inside the function to maintain the scope of a within outFun.
Let's look at the following code:
Js Code

Function outerFun ()
{
// No var
A = 0;
Alert ();
}
Var a = 4;
OuterFun ();
Alert ();
The result is 0, 0. Why?
The scope chain is the term used to describe a path. The variable value can be determined along this path. when a = 0 is executed, because the var keyword is not used, the value assignment operation will link to var a = 4 along the scope and change its value.
Certificate --------------------------------------------------------------------------------------------------------------------------------------------------
If you are not very familiar with the javascript closure, then please refer to the reprinted Article below :( reprint: http://www.felixwoo.com/archives/247)
 
1. What is a closure?
The official explanation is: a closure is an expression (usually a function) that has many variables and is bound to these variables. Therefore, these variables are part of the expression.
I believe that few people can directly understand this sentence, because he described it too academic. In fact, all functions in JavaScript are closures. But in general, nested functions produce more powerful closures, which are also called "closures" in most cases ". See the following code:
Function (){
Var I = 0;
Function B () {alert (++ I );}
Return B;
}
Var c = ();
C ();
This code has two features:
1. function B is nested in function;
2. function a Returns function B.
Reference relationship

 



 

In this way, after var c = a () is executed, variable c actually points to function B and then executes c () then a window will pop up showing the I value (the first time is 1 ). This Code actually creates a closure. Why? Because variable c outside function a references function B in function a, that is:
When function a's internal function B is referenced by a variable outside function a, a closure is created.
Let's be more thorough. The so-called "closure" refers to defining another function in the constructor as the method function of the target object, and the method function of this object references temporary variables in the outer function body in turn. This allows the target object to indirectly retain the temporary variable value used by the original constructor as long as it can maintain its method throughout the lifetime. Although the call to the initial constructor has ended, the name of the temporary variable has also disappeared, but the value of the variable can always be referenced in the method of the object, this value can only be accessed in this way. Even if the same constructor is called again, only new objects and methods are generated. The new temporary variables only correspond to new values, which are independent of those called last time.
Ii. What is the function of closure?
In short, the function of the closure is that after a executes and returns, the closure makes the garbage collection mechanism of Javascript GC not to reclaim the resources occupied by, because the execution of the internal function B of a depends on the variables in. This is a straightforward description of the function of the closure, which is neither professional nor rigorous, but probably means that the process of understanding the closure needs to be gradual.
In the above example, because of the existence of the closure, the I in a always exists after function a returns, so that each execution of c (), I is the value of alert after auto-increment 1. Www.2cto.com
Then let's imagine another situation. If a does not return function B, the situation is completely different. Because after a is executed, B is not returned to the external world of a, but is referenced by a. At this time, a will only be referenced by B, therefore, functions a and B are referenced by each other without being disturbed by the outside world (referenced by the outside world), and functions a and B are recycled by GC. (The garbage collection mechanism of Javascript will be described in detail later)
3. microview of the world in the closure
To learn more about closures and the relationship between function a and nested function B, we need to introduce several other concepts: the function execution environment (excution context), and the activity object (call object) scope and scope chain ). The process from definition to execution of function a is used as an example to describe these concepts.
1. when defining function a, the js interpreter sets the scope chain of function a to the "Environment" where a is located when defining function a. If function a is a global function, the scope chain contains only window objects.
2. When function a is executed, function a enters the corresponding execution environment (excution context ).
3. In the process of creating the execution environment, a scope attribute, that is, the scope of a, is added for a, and its value is the scope chain in step 1. That is, the scope chain of a. scope =.
4. A call object will be created in the execution environment ). An activity object is also an object with attributes, but it does not have a prototype and cannot be directly accessed through JavaScript code. After creating the activity object, add the activity object to the top of the scope chain of. In this case, the scope chain of a contains two objects: The activity object of a and the window object.
5. The next step is to add an arguments attribute to the activity object, which stores the parameters passed when calling function.
6. Finally, add the parameters of all function a and the reference of function B to the activity object of function. In this step, the definition of function B is completed. As in step 1, the scope chain of function B is set to the environment defined by B, that is, the scope of function.
At this point, the steps from definition to execution of function a are completed. At this time, a returns the reference of function B to function c, and the scope chain of function B contains the reference to the activity object of function, that is to say, B can access all variables and functions defined in. Function B is referenced by Function c, and function B is dependent on function a. Therefore, function a is not recycled by GC after return.
When function B is executed, it will be the same as the above steps. Therefore, during execution, B's scope chain contains three objects: B's activity object, a's activity object, and window object, as shown in:
 

 


 

When accessing a variable in function B, the search order is:

Search for its own activity object first. If it exists, return. If it does not exist, search for the activity object of function a until it is found.
If function B has a prototype object, search for its own prototype object after searching for its own activity object. This is the Variable Search Mechanism in Javascript.
If the entire scope chain cannot be found, undefined is returned.
This section describes two important words: function definition and execution. The scope of the function is determined when the function is defined, rather than when the function is executed (see steps 1 and 3 ). Use a piece of code to illustrate this problem:

Function f (x ){
Var g = function () {return x ;}
Return g;
}
Var h = f (1 );
Alert (h (); in this Code, the variable h points to the anonymous function in f (returned by g ).

Assume that the scope of function h is determined by the execution of alert (h (), then the scope chain of h is: h activity object-> alert activity object-> window object.
Assume that the scope of function h is determined during definition, that is, the anonymous function pointed to by h has already determined the scope. During execution, the scope chain of h is: h activity Object> f activity Object> window object.
If the first hypothesis is true, the output value is undefined. If the second hypothesis is true, the output value is 1.

The running result proves that the 2nd assumptions are correct, indicating that the function scope is indeed determined when the function is defined.
 

Iv. application scenarios of closures
Protect the security of variables in the function. Taking the initial example as an example, in function a, I can only access function B, but cannot access function B through other channels, thus protecting the security of I.

Maintain a variable in the memory. Still, for example, because of the closure, the I in function a is always in the memory, so each execution of c () will add 1 to the I self.
Implement JS private attributes and private methods by protecting the security of variables (cannot be accessed externally)
Private attributes and methods cannot be accessed outside the Constructor.
Function Constructor (...){
Var that = this;
Var membername = value;
Function membername (...){...}
}

The above three points are the most basic application scenarios of closures. Many classic cases are based on this.
 

V. Garbage collection mechanism of Javascript

In Javascript, if an object is no longer referenced, the object will be recycled by GC. If two objects are referenced by each other and no longer referenced by 3rd, the two objects referenced by each other will be recycled. Because function a is referenced by function B and function B is referenced by Function c outside of function a, this is why function a is not recycled after execution.

 

Vi. Conclusion

Understanding the closure of JavaScript is the only way to move towards a senior JavaScript programmer. Only by understanding its interpretation and running mechanism can we write safer and more elegant code.

 

From tonghaikou
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.