1. What is a closure
A closure is a function that has permission to access variables in another function scope.
Simply put, Javascript allows the use of internal functions - that is, function definitions and function expressions are located in the function body of another function. Moreover, these internal functions can access all local variables, parameters, and other internal functions declared in the external function where they reside. When one of these internal functions is called outside the external function containing them, a closure is formed.
2. The scope of variables
To understand closures, you must first understand the scope of variables.
There are only two types of scopes of variables: global variables and local variables.
The special feature of Javascript language is that global variables can be read directly within functions.
The variables of external functions can be accessed in the internal function because the scope chain of the internal function contains the scope of the external function;
It can also be understood as: the range of action of the internal function radiates to the range of action of the external function;
var n=999;function f1(){ alert(n);}f1(); // 999On the other hand, local variables inside the function are naturally not read outside the function.
function f1(){ var n=999;}alert(n); // errorThere is a place to note here. When declaring variables internally, you must use the var command. If not, you actually declare a global variable!
function f1(){ n=999;}f1();alert(n); // 9993. Several ways to write and use closures
3.1. Add some properties to the function
function Circle(r) { this.r = r; } Circle.PI = 3.14159; Circle.prototype.area = function() { return Circle.PI * this.r * this.r; } var c = new Circle(1.0); alert(c.area()); //3.141593.2. Declare a variable and assign a function to the variable as a value.
var Circle = function() { var obj = new Object(); obj.PI = 3.14159; obj.area = function( r ) { return this.PI * r * r; } return obj; } var c = new Circle(); alert( c.area( 1.0 ) ); //3.141593.3. This method is used more frequently and is the most convenient. var obj = {} is to declare an empty object
var Circle={ "PI":3.14159, "area":function(r){ return this.PI * r * r; } }; alert( Circle.area(1.0) );//3.141594. The main function 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.
4.1. 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 f1(){ var n=999; function f2(){ alert(n); // 999 }}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?
function f1(){ var n=999; function f2(){ alert(n); } return f2;}var result=f1();result(); // 9994.2. How to always save the value of a variable in memory?
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2;}var result=f1();result(); // 999nAdd();result(); // 1000In 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 recycled 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. Closures and this object
Using this object in closures can cause some problems. Because the execution of anonymous functions is global, its this object usually points to window. The code is as follows:
var name = "The window";var object = {name:"My object",getNameFun:function(){return function(){return this.name;};}};alert(object.getNameFun(){}); //"The window" (in non-strict mode)Save this object in the external scope in a variable that can be accessed by a closure, and the closure can access the object. The code is as follows:
var name = "The window";var object = {name:"My object",getNameFun:function(){var that = this;return function(){return that.name;};}};alert(object.getNameFun(){}); //"My object"6. Closures and memory leaks
Specifically, if an HTML element is stored in the scope of the closure, it means that the element cannot be destroyed. as follows:
function assignHandler(){var element = document.getElementById("someElement");element.onclick = function(){alert(element.id);}}The above code creates a closure as the element element event handler, and this closure creates a circular reference. Since anonymous functions save a reference to the active object of assignHandler(), it will not be possible to reduce the number of references to the element. As long as an anonymous function exists, the number of references to the element is at least 1, so the memory it occupies will not be recycled.
Resolve internal recycling problems by rewriting the code:
function assignHandler(){var element = document.getElementById("someElement");var id = element.id;element.onclick = function(){alert(id);}element = null;}In the above code, the implementation closure does not directly refer to element, and a reference will still be saved in the active object containing the function. Therefore, it is necessary to set the element variable to null, so that the memory it occupies can be recycled normally.
7. 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.
The above is a detailed explanation of the writing and function of closures in JavaScript introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support to Wulin.com website!