Javascript closures and applications that must be known in front-end development

Source: Internet
Author: User
Tags closure definition delete cache

In the prototype and inheritance document of JS, which must be known for front-end development, we have mentioned writing closures below. In addition, we have recently discovered that we need to enhance the application capabilities of closures, so this article cannot be dragged on. This article describes function closures and does not involve object closures (such as ). If you think there is a deviation in what I said, please make a brick. Thank you for your advice.
I. Closure Theory
First, you must understand the following concepts:

Execution Environment
Each time a function is called (when a function is executed), the system creates a closed local running environment for the function, that is, the execution environment of the function. Functions are always executed in their own execution environment, such as reading and writing local variables, function parameters, and running internal logic. The process of creating an execution environment includes the scope of the created function, and the function is also executed under its own scope. From another perspective, each function execution environment has a scope chain. The scope chain of a sub-function includes the scope chain of its parent function. For details about the scope and scope chain, see the following.

Scope, scope chain, and call object
Function scopes are divided into lexical scopes and dynamic scopes.
The Lexical scope is the scope of the function definition, that is, the static scope. When a function is defined, its lexical scope is determined. The Lexical scope indicates the scope of the function under the nested relationship of the function structure. At this time, the scope chain of the function is formed. The scope chain concatenates these scopes with nested hierarchies. The internal [scope] attribute of the function points to the scope chain.
The dynamic scope is the scope of the function call execution. When a function is called, first point the [[scope] attribute inside the function to the function's scope chain, and then create a call object, use this call object to record the function parameters and the local variables of the function and place them at the top of the scope chain. The dynamic scope is created by adding the call object to the top of the scope chain. In this case, [scope] Except for the scope chain with definitions, it also has the call object created during the call. In other words, the scope in the execution environment equals to the scope chain determined when the function is defined plus the called object created by the function, thus forming a new scope chain. So it is a dynamic scope, and the scope chain also changes. The scope here is actually an object chain. These objects are the call objects created when the function is called, as well as the above-layer call objects until the global objects at the top.
For example, if function A in the global environment is nested with function B, the scope chain of function B is: Scope of function B-> scope of function A-> scope of global window. When function B is called, it looks for an identifier based on the scope of function B-> the scope of function A-> the scope of global window, in fact, it is searched by function B's calling Object> function A's calling Object> global object. That is to say, when a function is called, the function's scope chain actually calls the object chain.

Closure
In a dynamic execution environment, data changes in real time. To keep the values of these non-durable variables, we use closures as a carrier to store these dynamic data (this is a good example after reading the following application ). Closure definition: the so-called "closure" refers to an expression (usually a function) with many variables and an environment bound to these variables ), therefore, these variables are part of the expression.
A closure is an internal function nested in a function. It can access all local variables, parameters, and other internal functions declared in an external function. When this internal function is called outside the external function, a closure is generated. (In fact, any function is a global internal function and can access global variables, so it is a closure of window)
For example:
Copy codeThe Code is as follows:
<Script type = "text/javascript">
Function f (x ){
Var a = 0;
A ++;
X ++;
Var inner = function (){
Return a + x;
}
Return inner;
}
Var test = f (1 );
Alert (test ());
</Script>

Garbage collection mechanism: if an object is no longer referenced, the object will be recycled.
Combined with the concepts mentioned above, the call object of f is created when var test = f (1) is executed. It is now recorded as obj, although the external execution environment is exited after execution, the inner of the internal function is referenced by the test variable outside the external function f. Because the object called by an external function (obj) has an attribute pointing to this internal function, and now this internal function is referenced, The called object (obj) will continue to exist and will not be recycled by the garbage collector, both function parameter x and local variable a are maintained in the called object. Although the called object cannot be directly accessed, the called object has become part of the internal function scope chain and can be accessed and modified by internal functions. Therefore, when you run test, you can access x and a correctly. Therefore, when an external function is executed, a closure is generated, and the variables of the referenced external function will continue to exist.
II. Application of closures
Application 1:
This is a problem I encountered when using js to simulate the Sorting Algorithm process. I want to output each inserted sorted array. If it is written in a loop
SetTimeout (function () {$ ("proc"). innerHTML + = arr + "<br/>" ;}, I * 500 );
We will find that each output is the final sorted array, because the arr array will not reserve the status value for each sort. To save the changing array values, we wrap a function outside to implement closures and store this dynamic data with closures. The following two methods are used to implement closures. One is to store the array values with parameters, and the other is to store the values with temporary variables, which must be copied in depth. All non-durable variables that need to be stored through closures can be implemented using temporary variables or parameters.
<! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ptml xmlns = "http://www.w3.org/1999/xhtml"> <pead> <title> </title> </pead> <body> var a = [4, 5, 6, 8, 7, 9, 3, 2, 1, 0]; <input type = "button" value = "insert Sort" onclick = "Sort. insert (); "/> Proc: </body> </ptml>
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]
Application 2:
This is a carefree example (click here to view the original post), bind the click event to each <li> node to bring up the cyclic index value. Written at first
Id. onclick = function () {alert (I);} id. onclick = function () {alert (I );}
It is found that all the pop-up objects are 4 instead of 1, 2, and 3, because the I value is 4 after the loop is complete. To save the value of I, we also use closures to implement:
<! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ptml xmlns = "http://www.w3.org/1999/xhtml"> <pead> <title> </title> </pead> <body> <ul> <li id = "a1"> aa </li> <li id = "a2"> aa </li> <li id = "a3"> aa </li> </ul> </body> </ptml>
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]
(Ps: var a = (function () {}) (); returns the same effect as var a = new function () {}, indicating self-executed functions .)
Application 3:
The following code is the cached application, catchNameArr. Save the catch value in the called object of the anonymous function. The returned object is referenced by the CachedBox variable, so that the called object of the anonymous function will not be recycled, thus retaining the catch value. You can use CachedBox. getCatch ("regionId");. If regionId cannot be found, it is retrieved from the background. catchNameArr is mainly used to prevent the cache from being too large.
Copy codeThe Code is as follows:
<Script type = "text/javascript">
Var CachedBox = (function (){
Var cache ={}, catchNameArr = [], catchMax = 10000;
Return {
GetCatch: function (name ){
If (name in cache ){
Return cache [name];
}
Var value = GetDataFromBackend ();
Cache [name] = value;
CatchNameArr. push (name );
This. clearOldCatch ();
Return value;
},
ClearOldCatch: function (){
If (catchNameArr. length> catchMax ){
Delete cache [catchNameArr. shift ()];
}
}
};
})();
</Script>

Similarly, you can use this idea to achieve your own growth ID.
Copy codeThe Code is as follows:
<Script type = "text/javascript">
Var GetId = (function (){
Var id = 0;
Return function (){
Return id ++;
}
})();
Var newId1 = GetId ();
Var newId2 = GetId ();
</Script>

Application 4:
This is an example of last month MM without worry (click here to view the original post). It is quite creative to use closures to implement the pause function of the program.
<Input type = "button" value = "continue" onclick = 'st (); '/>
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]
Extending this role, I thought of using it to implement window. confirm.
<! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ptml xmlns = "http://www.w3.org/1999/xhtml"> <pead> <title> </title> <style type = "text/css"> body {font-family: arial; font-size: 13px; background-color: # FFFFFF;} # confirmDiv {width: 200px; height: 100px; border: dashed 1px black; position: absolute; left: 200px; top: 150px;} < /Style> </pead> <body> <input name = "btn2" type = "button" value = "delete" onclick = "doConfirm ('confirmdiv '); "/> <p> are you sure you want to delete it? </P> <input type = "button" value = "OK" onclick = "doConfirm ('confirmdiv ') (true ); "/> <input type =" button "value =" cancel "onclick =" doConfirm ('confirmdiv ') (false); "/> </body> </ptml>
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]
After reading the above applications, I went back to the previous sentence: in a dynamic execution environment, data changes in real time. In order to keep the values of these non-persistent variables, we use closures to store these dynamic data. This is the function of the closure. That is to say, when we encounter the need to store dynamically changed data or the data to be recycled, we can wrap a function to form a closure.
Of course, the closure will cause the calling objects of many external functions to be released, and the abuse of the closure will cause memory leakage. Therefore, we need to estimate the side effects of the closure in the case of frequent closure generation.
Complete. Hope to help you.
Jay Chow
Source: http://ljchow.cnblogs.com

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.