Closure (closure) is the concept of functional programming, appearing in the 1960s, the earliest implementation of the closure language is Scheme, which is a dialect of LISP. After that, closure features are widely absorbed in other languages.
The strict definition of closures is "a collection of functions (environments) and their closed free variables." "This definition is a bit obscure to everyone, so let's start with examples and less rigorous explanations to explain what a closure is, and then illustrate some of the classic closures."
What is closure
In layman's terms, every function in JavaScript is a closure, but a function that is usually nested in meaning is more capable of
To show the characteristics of closures, consider the following example:
var generateclosure = function () {
var count = 0;
var get = function () {
count + +;
return count;
};
return get;
};
var counter = generateclosure ();
Console.log (counter ()); Output 1
console.log (counter ());//Output 2
console.log (counter ());//Output 3
In this code, the Generateclosure () function has a local variable count with an initial value of 0. There is also a function called GET, which adds 1 to the count variable in its parent scope, the generateclosure () function, and returns the value of count. The return value of the Generateclosure () is the Get function. On the outside we call the Generateclosure () function through the counter variable and get its return value, which is the Getting function, and then repeatedly call counter (), and we find that each return value is incremented by 1.
Let's look at the characteristics of the above example, as the usual imperative programming thinking understands that count is a variable within the Generateclosure function, and that its lifecycle is the period when the generateclosure is invoked, when generateclosure When you return from the call stack, the space for the Count variable request is released. The problem is that after the generateclosure () call ends, counter () refers to the "freed" Count variable, and instead of making a mistake, it modifies and returns count every time the counter () is invoked. What the hell is going on here?
This is what the so-called closure features are. When a function returns a function defined within it, a closure is generated, which includes not only the returned function, but also the defined environment of the function. In the example above, when the internal function of the function generateclosure () is referenced by an external variable counter, the local variable of counter and Generateclosure () is a closure. If it's not clear enough, the following example can help
you understand:
var generateclosure = function () {
var count = 0;
var get = function () {
count + +;
return count;
};
return get;
};
var counter1 = Generateclosure ();
var counter2 = Generateclosure ();
Console.log (Counter1 ()); Output 1
console.log (Counter2 ());//Output 1
console.log (Counter1 ());//Output 2
console.log (Counter1 ());//Output 3
Console.log (Counter2 ());//Output 2
The above example explains how closures are generated: Counter1 and Counter2 each invoke the Generateclosure () function, generating two instances of closures, each of which are referenced in their respective operating environments. We can understand that when generateclosure () returns the Get function, the internal variable (that is, the count variable) of the Generateclosure () function that may be referenced privately is returned, and a copy is generated in memory, after Two instances of the function returned by Generateclosure () Counter1 and Counter2 are independent of each other.
Use of closures
1. Nested callback Functions
Closures have two main uses, one is to implement nested callback functions, and the other is to hide the details of the object. Let's look at the following code example to learn about nested callback functions. The following code uses MongoDB in Node.js to implement a simple user-enhancing feature:
Exports.add_user = function (User_info, callback) {
var uid = parseint (user_info[' uid ']);
Mongodb.open (function (err, db) {
if err) {callback (ERR);
Db.collection (' Users ', function (err, collection) {
if (err) {callback (ERR);
Collection.ensureindex ("UID", function (err) {
if (err) {callback (ERR);
Collection.ensureindex ("username", function (err) {
if (err) {callback (ERR);
Collection.findone ({Uid:uid}, function (err) {
if (err) {callback (ERR);
if (DOC) {
callback (' occupied ');
} else {
var user = {
uid:uid,
user:user_info,
};
Collection.insert (user, function (err) {
callback (err);});}});});
};
If you are unfamiliar with node.js or MongoDB, it doesn't matter, you don't need to understand the details, just look at the logical logic. This code uses the layer nesting of closures, and each layer is nested with a callback function. The callback function does not execute immediately, but waits for the requested function to be recalled after the corresponding request has been processed. As we can see, there is a reference to callback in each layer of nesting, and the innermost definition of the UID variable is also used at the top-level. Because of the closure mechanism, even if the outer function has finished executing, the variables requested in the scope are not released because the inner function may also refer to these variables, which perfectly implements the nested asynchronous callback.
2, the realization of private members
We know that JavaScript objects do not have private properties, which means that each attribute of the object is exposed to the outside. This can be a security risk, such as the user of the object directly modify a property, causing the consistency of the object's internal data is destroyed. JavaScript uses a convention to underline all private properties (for example, _myprivateprop), indicating that the property is private and that the external object should not read it directly. But this is an informal agreement, assuming that the user of the object does not do so, is there a stricter mechanism? The answer is yes, it can be done through closures. Let's take another look at the previous example:
var generateclosure = function () {
var count = 0;
var get = function () {
count + +;
return count;
};
return get;
};
var counter = generateclosure ();
Console.log (counter ()); Output 1
console.log (counter ());//Output 2
console.log (counter ());//Output 3
We can see that only the call to counter () can access the count variable in the closure and add 1 to it by rule, and there is no way to find the count variable otherwise. Inspired by this simple example, we can encapsulate an object with a closure, and only return an object with an "accessor" to hide the details.
This is the full content of this article, I hope to help you better learn to understand the JavaScript closure.