Closure is a difficulty in the Javascript language and its feature. Many advanced applications rely on closures to implement. I have been exposed to the concept of closures for a long time, but I have been confused and have not been able to understand what JavaScript closures are and what they are useful. Today I saw an article on JavaScript closures (original link) on the Internet. It was very well explained. Now I have completely understood that JavaScript closures are a magical thing and the purpose of closures. I will write them here to share with you. I hope that friends who do not understand JavaScript closures can understand closures after reading them! Most of the following content comes from the original text. I added some code comments, operation renderings and a little modification to the original text for easy understanding!
1. The scope of variables
To understand closures, you must first understand Javascript's special variable scope.
In JavaScript, the scope of variables is divided into two types: global variables and local variables.
In Javascript, global variables can be read directly inside a function.
var n=;//Define the global variable nfunction f(){ alert("Access the global variable n, n="+n);//Access the global variable n}f(); //Running results:
But the other way around is not possible, local variables inside the function cannot be read outside the function.
function f(){ var n=;//Define the local variable n}alert("Access the local variable n outside the function, n="+n); //Access the local variable n outside the function, error: n is not definedRunning results:
There is a place to note here. When declaring variables internally, you must use the var command. If not, it is actually a global variable declared!
function f(){ n=;}f();alert("n is not declared with var inside the f1 function, at this time n is a global variable, /r/n proof: n="+n+", the result of window.n==n is: "+(window.n==n));Running results:
2. How to read local variables from the outside?
For various reasons, we sometimes need to get local variables within the function. However, as mentioned earlier, under normal circumstances, this cannot be done and can only be achieved through workarounds.
That is to define another function inside the function.
function f(){ var n=;// local variable n inside f function// Define a f function function f(){// Inside f function, alert(n); // }}In the above code, function f2 is included inside function f1, and all local variables inside f1 are visible to f2. But the other way around is not possible. Local variables inside f2 are invisible to f1. This is the "chain scope" structure unique to the Javascript language. The child objects will look upwards level by level for all parent objects variables. Therefore, all variables of the parent object are visible to the child object, otherwise it is not true. Since f2 can read local variables in f1, as long as f2 is used as the return value, can't we read its internal variables outside f1? Some people may have questions. F2 is a function, how can it be returned as the return value of the f1 function? In fact, it is OK. The function name in JavaScript itself is a variable, so the function can also be used as a normal variable. That is, not only can one function be passed to another function like passing parameters, but one function can also be returned as the return value of another function.
function f(){ var n=;//local variable n//f function declared inside f function f(){ alert(n); } return f;//use f function as the return value of f function} var result=f();//The return value after f is called is an f function, and result is f function result(); // 999, call f2 functionRunning results:
3. The concept of closure
The f2 function in the previous section of the code is the closure. The definition of "closure" in various professional documents is very abstract. For example, there is a closure definition: "A JavaScript closure is a variable it obtains from the previous level function or scope in another scope, and these variables will not be destroyed as the execution of the previous level function is completed." It is difficult for me to understand such a closure definition. My understanding is that a closure is a function that can read variables inside other functions. Since in Javascript language, only subfunctions inside functions can read local variables, closures can be simply understood as "functions defined inside a function". So, in essence, a closure is a bridge connecting the inside and the outside of the function.
4. The purpose of closure
Closures can be used in many places. It has two biggest uses, one is that the variables inside the function can be read as mentioned above, and the other is that the values of these variables are always kept in memory.
How to understand this sentence? Please see the code below.
function f(){ var n=;//nAdd is a global variable that is not declared using var. This variable now points to an anonymous function declared inside the f function nAdd=function(){n+=} function f(){ alert(n); } return f; } var result=f();//result is the f function result();//The first call to the result function nAdd();//nAdd represents an anonymous function declared inside the f function, nAdd() is the anonymous function result();//The second call to the result function 1000Running results:
In this code, result is actually the closure f2 function. 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 kept in memory and is not automatically cleared after f1 is called.
Why is this happening? The reason is that f1 is the parent function of f2, and f2 is assigned to a global variable, which causes f2 to always be in memory, and the existence of f2 depends on f1. Therefore, f1 is always in memory and will not be collected by the garbage collection mechanism after the call is finished.
Another noteworthy point in this code is that the line "nAdd=function(){n+=1}" is first used before nAdd, so nAdd is a global variable, not a local variable. Secondly, the value of nAdd is an anonymous function, and this anonymous function itself is also a closure, so nAdd is equivalent to a setter, which can operate on local variables inside the function outside the function.
5. Notes on using closures
1) Since closures will cause all variables in the function to be stored in memory, and the memory consumption is very large, closures cannot be abused, otherwise it will cause performance problems of the web page and may lead to memory leakage in IE. The solution is to delete all local variables that are not used before exiting the function.
2) The closure will change the value of the variable inside 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 the internal variable as its private property, be careful not to change the value of the internal variable of the parent function at will.
6. Thinking questions
If you can understand the running results of the following two pieces of code, you should be considered understanding the running mechanism of the closure.
Code Snippet 1:
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()());Running results:
Code Snippet Two:
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()()());Running results:
The following comments are added to the code to analyze the running results of the above two code snippets:
Code Snippet 1:
The analysis is as follows:
/*In JavaScript, the JavaScript global objects, global functions and global variables we declare will automatically become members of the window object. Global variables are properties of window objects. Global functions are methods of window objects. */var name = "The Window";//Declare a global variable name, and at this time the global variable name will automatically become an attribute of the window object //Proof: alert("window.name: "+window.name);//You can access the name in the form of window.name (object name. attribute name), then it proves that the global variable name will automatically become an attribute of the window object //Declare the global object object, and at this time the global variable object object will automatically become an attribute of the window object var object = { name : "My Object",//Attribute name of the object getNameFunc: function(){//getNameFunc function of object object//The return value of the getNameFunc method of object object is an anonymous function return function(){//At this time, which object refers to the window object, which object calls the function where this is located, and which object refers to which object. //Prove that this in the anonymous function represents a window object instead of an objectalert("this==object result is: "+(this==object)); alert("this==window result is: "+(this==window)); return this.name;// Since this represents a window object, then this.name naturally accesses the name of the window object "The Window" }; }};//Proof: The global object object is an attribute of the window object alert("window.object:"+window.object);alert("window.object.name:"+window.object.name);/*After calling the getNameFunc method, an anonymous method is returned. At this time, retFn represents an anonymous method. Now it is equivalent to giving the anonymous method a name retFn. At this time, the retFn function automatically becomes a function of the window object*/var retFn = object.getNameFunc();alert(retFn());//Calling the returned anonymous method, so who is calling this anonymous method? It is a window object //Proof: the retFn function is a function of the window object alert("window.retFn(): "+window.retFn());//You can call the retFn method in the form of window.retFn() (object name. method name), then it proves that the retFn function is a function of the window objectCode Snippet Two:
The analysis is as follows:
var name = "The Window";//Global variable name//Global object objectvar object = { name : "My Object", getNameFunc : function(){/*Which object does this represent this at this time? This represents the object object. Which object calls the function where this is located? This refers to which object has been executed that = this, and that also represents the object object*/var that = this;//that is a local variable declared in the getNameFunc function//Prove that this in the getNameFunc function represents the object object instead of windowalert("this==object result is: "+(this==object)); alert("this==window result is: "+(this==window));//Prove that represents the object object alert("that==object result is: "+(that==object)); return function(){/*that is a local variable declared in the getNameFunc function. Under normal circumstances, after the getNameFunc function call is completed, the local variable that will be recycled by JavaScript's GC, freeing up the memory space occupied by the local variable that, but now that can be used normally and has not been recycled. The reason is that getNameFunc is the parent function of the anonymous function. After the getNameFunc function is called, the anonymous function will be returned and assigned to a global variable retFn, which causes the anonymous function to always be in memory, and the existence of the anonymous function depends on the getNameFunc function. Therefore, the getNameFunc function is always in memory and will not be recycled by the garbage collection mechanism after the call is finished. Since the getNameFunc function is always in memory, the that local variable declared inside the getNameFunc function will always exist in memory. Since it exists, of course it can continue to be used. */ return that.name;//that represents the object object, so that.name naturally accesses the object object name "My Object" }; } };var retFn = object.getNameFunc();//After calling the getNameFunc method, an anonymous method is returned. At this time, retFn represents an anonymous method, which is now equivalent to giving the anonymous method a name is retFn alert(retFn());Finally, I also attached an example I wrote when I learned JavaScript closures before:
<script type="text/javascript">function A(){var i = ;//Declare the local variable i inside function A/Declare the subfunction bfunction b(){alert("i = "+(++i));//Access the local variable i declared inside function A within function A} return b;//Return the address of the function b}/*After executing var c = After A(), the variable c actually points to the function b. b. The variable i is used. After executing c(), a window will pop up to display the value of i (the first time) and this code actually creates a closure, because the variable c outside of function a refers to the function b inside function a. That is to say: when the internal function b of function a is referenced by a variable outside function a, a so-called "closure" closure is created. After a has been executed and returned, the closure makes the JavaScript garbage collection mechanism GC will not recycle the resources occupied by a, because the execution of the internal function b of a needs to rely on the variable in a */A();//There will definitely be space in memory. After A() is executed, GC will recycle the memory space allocated for i var c = A();//This usage, GC will not treat i as garbage and c();//Equivalent to calling b(), the result is: i=c();//The result is: i=c();//The result is: i=c();//The result is: i=</script>Running results:
The above content is the detailed explanation of the JavaScript closure (Closure) code of the JavaScript knowledge points summarized (16) introduced by the editor. I hope it will be helpful to everyone!