Basics of javascript closure-js tutorial

Source: Internet
Author: User
Tags delete cache
Closures have always been mysterious and profound to programmers, including JavaScript programmers. In fact, the concept of closures is not very understandable in functional programming languages, if functions are well understood as basic concepts such as independent objects, it is quite easy to understand the concept of closures and apply them in practical programming practices.

In terms of DOM event processing, most programmers are even using closures without knowing it. In this case, the bug of the JavaScript engine embedded in the browser may cause memory leakage. This problem can be ignored. It is often difficult for programmers to debug the engine on their own.
A simple statement is used to describe the closure concept in JavaScript: In JavaScript, functions are objects, objects are set of attributes, and attribute values can be objects, defining a function in a function is taken for granted. If the function inner is declared inside the function func AND inner is called outside the function, a closure is generated.
Closure features:
Let's look at an example. If you do not understand the features of JavaScript, it is difficult to find the reason:

The Code is as follows:


Var outter = [];
Function clouseTest (){
Var array = ["one", "two", "three", "four"];
For (var I = 0; I <array. length; I ++ ){
Var x = {};
X. no = I;
X. text = array [I];
X. invoke = function (){
Print (I );
}
Outter. push (x );
}
}
// Call this function
ClouseTest ();
Print (outter [0]. invoke ());
Print (outter [1]. invoke ());
Print (outter [2]. invoke ());
Print (outter [3]. invoke ());


What are the running results? Many beginners may come up with the following answer:
0
1
2
3
However, run this program and the result is:
4
4
4
4
In fact, such a statement x. invoke = function () {print (I);} is not executed, but a function object with the function body "print (I);" is constructed. When I = 4, iteration stops, external functions return, and outter [0] is called again. when invoke (), the I value is still 4, so the invoke of each element in the outter array returns the I value: 4. How can this problem be solved? We can declare an anonymous function and execute it immediately:

The Code is as follows:


Var outter = [];
Function clouseTest2 (){
Var array = ["one", "two", "three", "four"];
For (var I = 0; I <array. length; I ++ ){
Var x = {};
X. no = I;
X. text = array [I];
X. invoke = function (no ){
Return function (){
Print (no );
}
} (I );
Outter. push (x );
}
}
ClouseTest2 ();
Script


In this example, we use x. when an invoke value is assigned, run a function that can return a function and then execute it immediately. In this way, x. every iteration of invoke is equivalent to executing such a statement:

The Code is as follows:


// X = 0
X. invoke = function () {print (0 );}
// X = 1
X. invoke = function () {print (1 );}
// X = 2
X. invoke = function () {print (2 );}
// X = 3
X. invoke = function () {print (3 );}


In this way, you can get the correct result. The closure allows you to reference variables that exist in external functions. However, it is not the value when the variable is created. Instead, it uses the last value of the variable in an external function.
Closure purpose:
Now, the concept of closure is clear. Let's take a look at the purpose of closure. In fact, we can do a lot of things by using closures. For example, it simulates the object-oriented code style. It is more elegant and concise to express the Code. In some aspects, it improves the code execution efficiency.

Cache:
Let's take a look at an example. Suppose we have a function object that takes a long time to process. Every call will take a long time, so we need to store the calculated value, when this function is called, it is first searched in the cache. If it cannot be found, it is computed, then the cache is updated, and the returned value is returned. If it is found, the searched value is directly returned.
The closure can do this because it does not release external references, so that the internal values of the function can be retained.

The Code is as follows:


Var CachedSearchBox = (function (){
Var cache = {},
Count = [];
Return {
AttachSearchBox: function (dsid ){
If (dsid in cache) {// if the result is in the cache
Return cache [dsid]; // directly return the objects in the cache
}
Var fsb = document. getElementById (dsid); // create
Cache [dsid] = fsb; // update cache
If (count. length> 100) {// keep the cache size <= 100
Delete cache [count. shift ()];
}
Return fsb;
},
ClearSearchBox: function (dsid ){
If (dsid in cache ){
Cache [dsid]. clearSelection ();
}
}
};
})();
Var obj1 = CachedSearchBox. attachSearchBox ("input1 ");
// Alert (obj1 );
Var obj2 = CachedSearchBox. attachSearchBox ("input1 ");


Implementation encapsulation:

The Code is as follows:


Var person = function (){
// The variable scope is inside the function and cannot be accessed from outside.
Var name = "default ";

Return {
GetName: function (){
Return name;
},
SetName: function (newName ){
Name = newName;
}
}
}();

Print (person. name); // direct access, the result is undefined
Print (person. getName ());
Person. setName ("jack ");
Print (person. getName ());


The result is as follows:
Undefined
Default
Jack

Another important purpose of closures is to implement objects in object-oriented systems. Traditional object Languages provide class templates so that different objects (class instances) have independent members and States, do not interfere with each other. Although JavaScript does not have a mechanism like this, we can simulate this mechanism by using closures. In the above example:

The Code is as follows:


Function Person (){
Var name = "default ";

Return {
GetName: function (){
Return name;
},
SetName: function (newName ){
Name = newName;
}
}
};
Var john = Person ();
Print (john. getName ());
John. setName ("john ");
Print (john. getName ());

Var jack = Person ();
Print (jack. getName ());
Jack. setName ("jack ");
Print (jack. getName ());


The running result is as follows:
Default
John
Default
Jack

Javascript closure should pay attention to the following issues:
1. Memory leakage:
In the implementation of different JavaScript interpreters, memory leakage may occur due to the defects of the interpreter itself. Memory leakage is a serious problem and will seriously affect the browser response speed, reduce user experience, and even cause no response from the browser. JavaScript interpreters have a garbage collection mechanism. Generally, the reference count is used. If the reference count of an object is zero, the garbage collection mechanism recycles it, this process is automatic. However, with the closure concept, this process becomes complicated. In the closure, because local variables may need to be used at some time in the future, therefore, the garbage collection mechanism does not process these locally referenced variables. If circular references occur, that is, the object A references B, B references C, and C references, in this case, the garbage collection mechanism draws the conclusion that the reference count is not zero, resulting in Memory leakage.

2. Context Reference:

The Code is as follows:


$ (Function (){
Var con = $ ("p # panel ");
This. id = "content ";
Con. click (function (){
Alert (this. id); // panel
});
});


What value does alert (this. id) reference? Many developers may make incorrect judgments based on the closure concept:
Content
The reason is that the display of this. id is assigned to content, and in the click callback, the formed closure will reference this. id, so the returned value is content. However, in fact, this alert will pop up a "panel", the reason is that this here, although the closure can reference local variables, but when it comes to this, the situation is somewhat subtle, because of the existence of the call object, this references the jQuery object con when the closure is called (when the click Event of the panel occurs. In the anonymous function, this. id = "content" is an operation on the anonymous function itself. Both this references not the same object.
If you want to access this value in the event handler function, we must make some changes:

The Code is as follows:


$ (Function (){
Var con = $ ("p # panel ");
This. id = "content ";
Var self = this;
Con. click (function (){
Alert (self. id); // content
});
});


In this way, we save the reference of an external local variable self in the event processing function, rather than this. This technique is often used in practical applications. We will discuss it in detail in the following chapters. For more information about closures, we will discuss in chapter 9, including the "closures" in other imperative languages and the application of closures in actual projects.
Appendix: due to its limited level, there may inevitably be mistakes in the text, or the language itself may be inappropriate. please correct me and make suggestions in time. This article is only for reference. Thank you!
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.