Home  >  Article  >  Web Front-end  >  Detailed explanation of how to write and function closures in JavaScript

Detailed explanation of how to write and function closures in JavaScript

高洛峰
高洛峰Original
2017-01-20 13:12:421270browse

1. What is a closure

A closure is a function that has access to a variable in the scope of another function.
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. Furthermore, these inner functions have access to all local variables, parameters, and other inner functions declared in the outer function in which they exist. A closure is formed when one of these inner functions is called outside the outer function that contains them.

2. The scope of variables

To understand closures, you must first understand the scope of variables.
The scope of variables is nothing more than two types: global variables and local variables.

The special thing about Javascript language is that global variables can be read directly inside the function.

The internal function can access the variables of the external function because the scope chain of the internal function includes the scope of the external function;

can also be understood as: the scope of the internal function Radiating to the scope of the external function;

var n=999;
function f1(){
 alert(n);
}
f1(); // 999

On the other hand, the local variables within the function cannot be read outside the function.

function f1(){
 var n=999;
}
alert(n); // error

There is one thing to note here. When declaring variables inside a function, you must use the var command. If you don't use it, you are actually declaring a global variable!

function f1(){
  n=999;
}
f1();
alert(n); // 999

3. Several ways to write and use closures

3.1. Add some attributes 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.14159

3.2. Declare a variable and assign a function as a value to the variable

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.14159

##3.3. This kind of The method is widely used and 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.14159

4. The main function of closure

Closure can be used in many places . Its greatest uses are two: one is to read the variables inside the function as mentioned earlier, and the other is to keep the values ​​of these variables in memory.

4.1. How to read local variables from the outside?

For various reasons, we sometimes need to get local variables within a function. However, as mentioned before, this is not possible under normal circumstances 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. At this time, all local variables inside f1 are visible to f2 . But the reverse doesn't work. The local variables inside f2 are invisible to f1. This is the "chain scope" structure unique to the Javascript language. The child object will search for the variables of all parent objects level by level. Therefore, all variables of the parent object are visible to the child object, but not vice versa.

Since f2 can read the local variables in f1, then 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(); // 999

4.2. How to keep 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(); // 999
nAdd();
result(); // 1000

In this code, result is actually the closure f2 function. It was run twice, the first time the value was 999, the second time the value was 1000. This proves that the local variable n in function f1 is always stored in memory and is not automatically cleared after f1 is called.

Why is this so? 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, so f1 is always in memory and will not be deleted after the call is completed. , recycled by the garbage collection mechanism (garbage collection).

Another thing worth noting in this code is the line "nAdd=function(){n+=1}". First of all, the var keyword is not used before nAdd, so nAdd is a global variable. rather than local variables. 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. Closure and this object

Using this object in a closure may 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"(在非严格模式下)

Save the this object in the external scope in a Within the variables that the closure can access, you can let the closure 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. Closure and memory leak

Specifically, if an HTML element is stored in the scope of the closure, it means This 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 event handler, and this closure creates a circular reference. Since the anonymous function saves a reference to the active object of assignHandler(), the number of references to element cannot be reduced. As long as the anonymous function exists, the reference number of element is at least 1, so the memory occupied by it will not be recycled.

Solve the problem of internal non-recycling by rewriting the code:

function assignHandler(){
var element = document.getElementById("someElement");
var id = element.id;
element.onclick = function(){
alert(id);
}
element = null;
}

The above code implements closure without directly referencing 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. Points of note when using closures

1) Since closures will cause the variables in the function to be stored in memory, which consumes a lot of memory, closures cannot be abused, otherwise It will cause performance problems on web pages and may cause memory leaks in IE. The solution is to delete all unused local variables 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, the closure as its public method, and the internal variables as its private value, you must be careful not to Feel free to change the value of the variable inside the parent function.

The above is the detailed explanation of the writing and function of closures in JavaScript introduced 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. . I would also like to thank you all for your support of the PHP Chinese website!

For more detailed explanations of the writing and functions of closures in JavaScript, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn