Basic knowledge sharing based on JavaScript closure basics

Source: Internet
Author: User
Tags anonymous closure garbage collection variable scope delete cache

If the basic concepts such as the scope, the function for the independent object understood better, the understanding closure concept and in the actual programming practice application is quite ripe for the feeling.

In the case of DOM, most programmers are already using closures rather than themselves, and in such cases, the problem of the JavaScript engine embedded in the browser may result in a memory leak, or the programmer's own debugging is often confused.
Describe the concept of closures in JavaScript with simple statements: Because in JavaScript, a function is an object, an object is a collection of attributes, and the value of a property can be an object, it is a matter of course to define a function within a function, if the function is declared inside a function func inner, It then invokes inner outside the function, which creates a closure.
Characteristics of closures:
Let's take a look at an example where it's hard to find out why you don't know the features of javascript:

Copy Code code 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 about the results of the operation? Many beginners may come up with the answer:
0
1
2
3
However, the results of running this program are:
4
4
4
4
In fact, in each iteration, such statements x.invoke = function () {print (i);} is not executed, just constructs a function body for "print (i);" Function object, that's all. And when i=4, the iteration stops, the external function returns, and when the Outter[0].invoke () is invoked, the value of I is still 4, so the invoke of each element in the Outter array returns the value of I: 4. How to solve this problem? We can declare an anonymous function and execute it immediately:
Copy Code code 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, when we assign a value to X.invoke, we run a function that can return a function, and then execute it immediately, so that each iteration of the X.invoke is equivalent to executing such a statement:
Copy Code code 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);}

So that we can get the correct result. Closures allow you to reference variables that exist in external functions. However, instead of using the variable when it was created, it uses the last value of the variable in the external function.
Closures for use:
Now that the concept of closure is clear, let's look at the purpose of closures. In fact, we can do a lot of things by using closures. For example, simulate object-oriented code style, more elegant, more concise expression of code, in some ways to improve the efficiency of code execution.

Cache:
To take another example, imagine that we have a function object that is time-consuming to process, each call takes a long time, so we need to store the computed value, when the function is called, first look in the cache, if it cannot be found, then compute, then update the cache and return the value, if found, Returns the lookup value directly.
Closures can do this because it does not release external references, so the values within the function can be preserved.
Copy Code code 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 to the object in the cache
}
var FSB = document.getElementById (DSID);/new
CACHE[DSID] = fsb;//Update cache
if (Count.length > 100) {//Yasumasa 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:
Copy Code code as follows:

var person = function () {
Variable scope is internal to function and cannot be accessed externally
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 results were as follows:
Undefined
Default
Jack

Another important use of closures is to implement object-oriented objects, and traditional object languages provide template mechanisms for classes, so that different objects (instances of classes) have independent members and states and do not interfere with each other. Although there is no such mechanism in JavaScript, we can simulate such a mechanism by using closures. Or in the example above:

Copy Code code 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 results of the operation are as follows:
Default
John
Default
Jack

The problems that JavaScript closures should note:
1. Memory leak:
In different JavaScript interpreter implementations, due to the defects of the interpreter itself, the use of closures can cause memory leaks, memory leaks is a serious problem, can seriously affect the browser's response speed, reduce user experience, and even the browser does not respond to such phenomena. JavaScript interpreters have garbage collection mechanisms, usually in the form of reference counting, if the reference count of an object is zero, the garbage collection mechanism reclaims it, and the process is automatic. However, with the concept of closures, the process becomes more complex, in closures, because local variables may need to be used at some point in the future, the garbage collection mechanism does not process these externally referenced local variables, and if a circular reference occurs, the object a refers to B,b reference C, and C references to a , this allows the garbage collection mechanism to conclude that its reference count is Non-zero, resulting in a memory leak.

2. Reference to Context:

Copy Code code as follows:

$ (function () {
var con = $ ("Div#panel");
This.id = "Content";
Con.click (function () {
alert (this.id);//panel
});
});

What value does alert (This.id) refer to here? Many developers may make erroneous judgments based on the concept of closures:
Content
The reason is that the this.id display is assigned to content, and in the click Callback, the resulting closure is referenced to the this.id, so the return value is content. In fact, this alert pops up "Panel", and the reason is this here, although closures can refer to local variables, but when it comes to this, the situation is a bit tricky because the invocation object exists so that when the closure is invoked ( When this panel's Click event occurs, this here refers to con, the jquery object. The this.id = "Content" In an anonymous function is an operation on the anonymous function itself. Two This does not refer to the same object.
if you want to access this value in the event handler function, we have to make some changes:
Copy Code code as follows:

$ (function () {
var con = $ ("Div#panel");
This.id = "Content";
var self = this;
Con.click (function () {
alert (self.id);//content
});
});

In this way, we save the reference to the external local variable self in the event handler function, not this. This technique has many applications in practice, and we discuss it in detail in the chapters that are in the back. For more on closures, we will discuss in detail in chapter Nineth, including discussion of "closures" in other imperative languages, applications of closures in real-world projects, and more.
attached: Because of its limited level, there are mistakes in the text, or the language itself is inappropriate, welcome to correct and make suggestions. This article is just for a draw, 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.