One of the most important features in Javascript is the use of closures. Because of the use of closures, the current scope can always access external scopes. Because Javascript has no block-level scope and only function scope, the use of closures is closely related to functions.
Simulate private variables
The code copy is as follows:
function Counter(start) {
var count = start;
return {
increment: function() {
count++;
},
get: function() {
return count;
}
}
}
var foo = Counter(4);
foo.increment();
foo.get(); // 5
Here Counter returns two closures: function increment and get. These two functions maintain access to the Counter scope, so they can access the variable count defined in the Count scope.
Working mechanism of private variables
Since Javascript cannot assign values and references to scopes, in the above example, there is no way to directly access the internal private variable count from the outside. The only way is to access it by defining the closure.
The code copy is as follows:
var foo = new Counter(4);
foo.hack = function() {
count = 1337;
};
The above code does not change the value of the count variable within the Counter scope, because hack is not defined within Counter. The above code will only create or overwrite the global variable count.
Closures in the loop
One of the easiest mistakes is to use closures within a loop.
The code copy is as follows:
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
The above code will not output 0 to 9, but will output 10 times continuously.
The anonymity above will keep a reference to the variable i. When the console.log function is called to start output, this is the loop that has ended, and the variable i is already 10.
To avoid the above error, we need to create a copy of the variable i value each time we loop.
Avoid quotation errors
To copy the value of a variable in the loop, the best way is to add an anonymous function to the outer layer and execute it immediately.
The code copy is as follows:
for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
This external anonymous function takes the loop variable i as the first parameter and copies its value to its own parameter e.
The external anonymous function passes the parameter e to setTimeout, so setTimeout has a reference to the parameter e. Moreover, the value of this parameter e will not change due to external loop changes.
There is another way to achieve the same effect, which is to return an anonymous function in the anonymous function in setTimeout:
The code copy is as follows:
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
In addition, it can also be achieved through the bind method.
The code copy is as follows:
for(var i = 0; i < 10; i++) {
setTimeout(console.log.bind(console, i), 1000);
}
At the end of the article, let’s summarize:
(1) Closure is a design principle. It simplifies user calls by analyzing the context, allowing the user to achieve his purpose without knowing it;
(2) The mainstream online articles on analysis of closures are actually contrary to the closure principle. If you need to know the details of the closure to be used well, this closure is a design failure;
(3) Try to learn as little as possible.