Front words
According to the definition of closure, we know that no matter through what means, as long as the internal function is passed outside its lexical scope, it will hold a reference to the original scope, no matter where the function is executed, it will use closure. Next, we'll look at 10 forms of closures in detail.
I. Return Value
One of the most common forms is that functions are returned as return values.
var F = function(){
var b = 'local';
var N = function(){
return b;
}
return N;
}
console.log(F()());
2. Function assignment
One variant is to assign an internal function to an external variable.
var inner;
var F = function(){
var b = 'local';
var N = function(){
return b;
};
inner = N;
};
F(); //This is equivalent to binding an internal function reference to an inner variable when calling the F function.
console.log(inner());
3. Functional parameters
Closure can be implemented in the form of function parameter transfer function.
//A parameter execution function is defined externally
var Inner = function(fn){
fn();
}
var F = function(){
var b = 'local';
var N = function(){
return b;
}
Inner(N); //When this function is called, the incoming parameter function is executed
}
F();
Four, IIFE
As can be seen from the previous example code, function F() is called immediately after declaration, so IIFE can be used instead. Note, however, that Inner() here can only be in the form of function declaration statements, not function expressions. (Not very understanding)
function Inner(fn){
console.log(fn());
}
(function(){
var b = 'local';
var N = function(){
return b;
}
Inner(N);
})();
V. Cyclic Assignment
One of the most common errors in closure problems is the error of circular assignment.
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]());//2
Correct Writing
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = (function fn(j){
return function test(){
return j;
}
})(i);
}
return arr;
}
var bar = foo();
console.log(bar[0]());//0
6. g(s)etter
By providing getter() and setter() functions, we keep the variables we manipulate inside the function to prevent them from being exposed to the outside world.
var getValue,setValue;
(function(){
var secret = 0;
getValue = function(){
return secret;
}
setValue = function(v){
if(typeof v === 'number'){
secret = v;
}
}
})();
console.log(getValue());//0
setValue(1);
console.log(getValue());//1
Iterator
We often use closures to implement an accumulator
var add = (function(){
var counter = 0;
return function() {
return ++counter;
}
})();
//When the immediate execution function above is finished, add now points to the anonymous function.
//So calling this add is actually equivalent to calling an anonymous function.
console.log(add()); //1
console.log(add()); //2
Similarly, you can easily implement an iterator using closures
function setup(x) {
var i = 0;
return function() {
return x[i++];
}
}
var next = setup(["a","b","c"]);
//Pass in an array and read each item in the array
console.log(next()); //"a"
console.log(next()); //"b"
console.log(next()); //"c"
VIII. DIVISION FOR THE FIRST TIME
var firstLoad = (function) {
var _list = [];
return function(id) {
if(_list.indexOf(id) >= 0) {
return false;
} else {
_list.push(id);
return true;
}
}
})()
//This is done by adding for the first time, then manipulating the incoming values, push ing the first time into the array, and returning true.
9. Caching mechanism
By adding caching mechanism to closure, the performance of functions can be improved without repeated calculation of the same parameters.
Code without caching
var mult = function() {
var a = 1;
for(var i=0; i<arguments.length; i++) {
a = a * arguments[i]
}
return a;
}
Code after adding caching mechanism
var mult = function(){
var cache = {};
var calculate = function(){
var a = 1;
for(var i = 0,len = arguments.length; i<len; i++){
a = a * arguments[i];
}
return a;
};
return function(){
var args = Array.prototype.join.call(arguments,',');
if(args in cache){
return cache[args];
}
return cache[args] = calculate.apply(null,arguments);
}
}()
10. img Objects
img objects are often used for data reporting
var report = function(src) {
var img = new Image();
img.src = src;
}
report("https://github.com/AFeng521web/photos")
However, in some low-level browsers, using report function to report data will lose about 30% of the data packets, that is to say, report function does not successfully initiate HTTP requests every time.
The reason is that img is a local variable in the report function. When the report function call is finished, the IMG local variable will be destroyed immediately, and it may not be time to issue an HTTP request. So this request will be lost.
Now wrap the img variable in a closure to resolve the problem of missing requests.
var report = (function() {
var imgs = [];
return function(src) {
var img = new Image();
imgs.push(img);
img.src = src;
}
})()
report("https://github.com/AFeng521web/photos")
Closure is used here. When the report function is executed, its execution environment will be destroyed, but because the inner function refers to its variables, it generates closures, so its variable object always exists in memory. Thus, the problem of data loss is well solved.