Home > Web Front-end > JS Tutorial > Understanding closures in javascript functional programming_javascript skills

Understanding closures in javascript functional programming_javascript skills

WBOY
Release: 2016-05-16 15:11:31
Original
1492 people have browsed it

Closure is a concept in functional programming that appeared in the 1960s. The earliest language to implement closure was Scheme, which is a dialect of LISP. Since then, closure features have been widely adopted by other languages.
The strict definition of a closure is "a set consisting of a function (environment) and its enclosed free variables." This definition is a bit obscure for everyone, so let's first explain it through examples and a less strict explanation. is a closure, and then gives examples of some classic uses of closures.

What is closure

In layman’s terms, every function in JavaScript is a closure, but in general, nested functions can better reflect
To show the characteristics of closure, please see the following example:

var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter = generateClosure();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3
Copy after login

In this code, there is a local variable count in the generateClosure() function, with an initial value of 0. There is also a function called get, which increases the count variable in its parent scope, the generateClosure() function, by 1, and returns the value of count. The return value of generateClosure() is the get function. Externally, we called the generateClosure() function through the counter variable and obtained its return value, which is the get function. Then we repeatedly called counter() several times, and we found that the returned value was incremented by 1 each time.
Let's take a look at the characteristics of the above example. According to the usual understanding of imperative programming thinking, count is a variable inside the generateClosure function. Its life cycle is the period when generateClosure is called. When generateClosure returns from the call stack, the count variable The applied space will be released. The problem is that after the call to generateClosure() ends, counter() refers to the "already released" count variable, and not only does no error occur, but count is modified and returned each time counter() is called. What's going on?
This is exactly the characteristic of so-called closure. When a function returns a function defined within it, a closure is generated. The closure not only includes the returned function, but also the environment in which the function is defined. In the above example, when the internal function get of the function generateClosure() is referenced by an external variable counter, the local variables of counter and generateClosure() are a closure. If it’s not clear enough, the following example may 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()); // 输出 1
console.log(counter2()); // 输出 1
console.log(counter1()); // 输出 2
console.log(counter1()); // 输出 3
console.log(counter2()); // 输出 2
Copy after login

The above example explains how closures are generated: counter1 and counter2 call the generateClosure() function respectively, generating two instances of closures, and the count variables they reference internally belong to their respective operating environments. We can understand that when generateClosure() returns the get function, the internal variables of the generateClosure() function that get may refer to (that is, the count variable) are also returned privately, and a copy is generated in the memory, and then generateClosure( ) The two instances of the returned function, counter1 and counter2, are independent of each other.

The purpose of closure

1. Nested callback function
Closures have two main uses, one is to implement nested callback functions, and the other is to hide the details of an object. Let's first look at the following code example to understand nested callback functions. The following code uses MongoDB in Node.js to implement a simple function of adding users:

exports.add_user = function(user_info, callback) {
var uid = parseInt(user_info['uid']);
mongodb.open(function(err, db) {
if (err) {callback(err); return;}
db.collection('users', function(err, collection) {
if (err) {callback(err); return;}
collection.ensureIndex("uid", function(err) {
if (err) {callback(err); return;}
collection.ensureIndex("username", function(err) {
if (err) {callback(err); return;}
collection.findOne({uid: uid}, function(err) {
if (err) {callback(err); return;}
if (doc) {
callback('occupied');
} else {
var user = {
uid: uid,
user: user_info,
};
collection.insert(user, function(err) {
callback(err);
});
}
});
});
});
});
});
};
Copy after login

If you are not familiar with Node.js or MongoDB, it doesn’t matter. You don’t need to understand the details, just understand the general logic. This code uses layers of nesting of closures, and each layer of nesting is a callback function. The callback function will not be executed immediately, but will be called back by the requested function after the corresponding request is processed. We can see that there is a reference to callback in each layer of nesting, and the innermost layer also uses the uid variable defined by the outer layer. Due to the existence of the closure mechanism, even if the outer function has been executed, the variables applied in its scope will not be released, because the inner function may still reference these variables, thus perfectly realizing the nested asynchronous callback. .

2. Implement private members
We know that JavaScript objects have no private properties, which means that every property of the object is exposed to the outside world. This may cause security risks, for example, if the user of the object directly modifies an attribute, causing the consistency of the internal data of the object to be destroyed, etc. JavaScript uses the convention to put an underscore before all private properties (such as _myPrivateProp) to indicate that this property is private and external objects should not read or write it directly. But this is just an informal agreement. Assuming that the user of the object does not do this, is there a more strict mechanism? The answer is yes, it can be achieved through closure. Let’s look at the previous example again:

var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter = generateClosure();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3
Copy after login

We can see that only calling counter() can access the count variable in the closure and increment it by 1 according to the rules. It is impossible to find the count variable in other ways. Inspired by this simple example, we can encapsulate an object with a closure and only return an "accessor" object to hide the details.

The above is the entire content of this article. I hope it can help everyone better learn and understand JavaScript closures.

Related labels:
source:php.cn
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template