JavaScript closures

JavaScript Closure

What is a closure

Closure, the official explanation of closure is: a variable with many variables and An expression (usually a function) of the environment to which these variables are bound, so that these variables are part of the expression. Characteristics of closure:

 1. As a reference to a function variable, it is activated when the function returns.

 2. A closure is a stack area that does not release resources when a function returns.

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. Several ways of writing and using closures

First of all, you must understand that everything in JS is an object, and functions are a type of object. Let's first look at the five ways to write closures and briefly understand what closures are. This will be explained in detail later.

//The first way of writing

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());

There is nothing special about this way of writing, it just adds some attributes to the function.

//The second way of writing

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 ) );

This way of writing is to declare a variable and assign a function as a value to the variable.

//The third way of writing

var Circle = new Object();  
Circle.PI = 3.14159;  
Circle.Area = function( r ) {  
       return this.PI * r * r;  
}  
alert( Circle.Area( 1.0 ) );

This method is best understood, which is to create a new object and then add properties and methods to the object.

//The fourth way of writing

var Circle={  
   "PI":3.14159,  
 "area":function(r){  
          return this.PI * r * r;  
        }  
};  
alert( Circle.area(1.0) );

This method is commonly used and is the most convenient. var obj = {} declares an empty object.

//The fifth way of writing

var Circle = new Function("this.PI = 3.14159;this.area = function( r ) {return r*r*this.PI;} ");

alert( (new Circle()).area(1.0) );

To be honest, I have never used this way of writing, everyone can just for reference.

Generally speaking, among the above methods, the 2nd and 4th are more common, and you can choose according to your habits.

The prototype commonly used in JS appears in the above code, so what is the use of prototype? Let’s take a look:

  var dom = function(){    
    };
    dom.Show = function(){
        alert("Show Message");
    }; 
    dom.prototype.Display = function(){
        alert("Property Message");
    };
    dom.Display(); //error
    dom.Show();  
    var d = new dom();
    d.Display();
    d.Show(); //error

Variable life cycle

The scope of global variables is global, that is, throughout the entire JavaScript program , global variables are everywhere.

The variables declared inside the function only work inside the function. These variables are local variables and their scope is local; the parameters of the function are also local and only work inside the function.

Counter Dilemma

Imagine if you want to count some values, and the counter is available in all functions.

You can use global variables and functions to set the counter increment:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>全局变量计数。</p>
<button type="button" onclick="myFunction()">计数!</button>
<p id="demo">0</p>
<script>
var counter = 0;
function add() {
    return counter += 1;
}
function myFunction(){
    document.getElementById("demo").innerHTML = add();
}
</script>
</body>
</html>

The counter value changes when the add() function is executed.

But here comes the problem, any script on the page can change the counter, even if the add() function is not called.

If I declare the counter within the function, the value of the counter cannot be modified without calling the function:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>局部变量计数。</p>
<button type="button" onclick="myFunction()">计数!</button>
<p id="demo">0</p>
<script>
function add() {
    var counter = 0;
    return counter += 1;
}
function myFunction(){
    document.getElementById("demo").innerHTML = add();
}
</script>
</body>
</html>

The above code will not be output correctly. Every time I call the add() function, the counter will Set to 1.

JavaScript built-in functions can solve this problem.

JavaScript embedded functions

All functions can access global variables.

In fact, in JavaScript, all functions can access the scope above them.

JavaScript supports nested functions. Nested functions can access the function variables of the upper level.

In this example, the embedded function plus() can access the counter variable of the parent function:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>局部变量计数。</p>
<p id="demo">0</p>
<script>
document.getElementById("demo").innerHTML = add();
function add() {
var counter = 0;
    function plus() {counter += 1;}
    plus();    
    return counter; 
}
</script>
</body>
</html>

If we can access the plus() function externally, this can solve the counter dilemma.

We also need to ensure that counter = 0 is only executed once.

We need closures.


Continuing Learning
||
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>局部变量计数。</p> <button type="button" onclick="myFunction()">计数!</button> <p id="demo">0</p> <script> var add = (function () { var counter = 0; return function () {return counter += 1;} })(); function myFunction(){ document.getElementById("demo").innerHTML = add(); } </script> </body> </html>
submitReset Code