Statement: Part of the contents refer to this article ICE-shou: Closure detail 1

A preface.

In our development of closures, often can be used as he fixes some problems, at the time of the interview, also often asked about the understanding of the closure, but in fact the concept of closure is not unified, but no matter how to describe, the core of it are like that, here is to explore how the closure to understand

Ii. Basic Knowledge:

1. The chain of action of variables

  • There are two types of JavaScript variables: global variables and local variables

  • Local variables are usually scoped inside functions, and those outside functions are considered global variables

  • In general, global variables can be accessed from inside a function, but variables inside a function cannot be accessed from outside

  • Javascript has a “chain scope” structure, where the chain scope can be understood as function nesting, and the child objects will look up all the variables of the parent object level by level. Therefore, all variables of the parent object are visible to the child object, and vice versa.

    var str1="hello";// Global variables
    function fun(){
    	var res="i am coming";// local variables in fun()
    }
    function funa(){
    	var str2=" world";// local variables in funa()
    	function funb(){
            function func(){
                console.log(str1);//hello
                console.log(str2);//world
    			console.log(res);/ / error, undefined
            }
    		func();
    	} 
    	funb();
    }
    funa();
    console.log(str2);/ / an error
    Copy the code

2. Anonymous function calls

  • Function expression call method

    var exc=function(){
        console.log("hello world");
    }
    exc();
    Copy the code
  • Since the call

    (function(){
          console.log("hello world"); }) ();Copy the code
  • Step by step a call

    function fun1(){
        var a=0;
        console.log(a);
        return function(){
            a++;
            console.log(a); }}// Notice the result of this call:fun1(); fun1()(); fun1()(); The output0
    //
    0
    1
    //
    0
    1
    Each time fun1() is executed,a is initialized to 0, and a++ is executed to 1
    Copy the code
  • It is assigned to a variable and called by the variable

    function fun1(){
        var a=0;
        console.log(a);
        return function(){
            a++;
            console.log(a); }}// Notice the result of this call:
    varres=fun1(); res(); res(); res(); The output0
    //
    1
    //
    2
    //
    3
    Fun1 () is executed only once, so a=0 is executed only once. Each subsequent execution of res() is an anonymous function, and each execution increments a
    Copy the code

3.

Let’s write a couple of models based on the descriptions in these books to see what closures look like, do they help us with our actual applications or why we need to write closures

Let’s start by looking at the descriptions of advanced JavaScript Programming and the Definitive JavaScript Guide

— JavaScript Advanced Programming

Closures are functions that have access to variables in the scope of another function;

— The Definitive JavaScript Guide

Technically speaking, all JavaScript functions are closures: they’re all objects, and they’re all associated with a scope chain.

function fn1() {
	var str = 'hello,world';
	function fn2() {
		console.log(str);// Access the fn1() function
	}
	fn2();
}
fn1();
Copy the code

instructions

Fn2 () is, by definition, a closure. What if this is a closure? The practical application is not particularly obvious, isn’t it just an example of following the variable scope access rules? Let’s take a more obvious example…

function fn1() {
	var str = 'hello world';
	function fn2() {
		console.log(str);
	}
	return fn2;
}
var fn3 = fn1();
fn3();
Copy the code

instructions

  • The lexical scope of fn2 accesses the scope of Fn1
  • Return fn2 as a value
  • After fn1 is executed, a reference to fn2 is assigned to fn3
  • Executing fn3 outputs the variable STR

Ok, so in this example, we see how closures can help us in practice, we think we can access variables outside the function, we can’t access variables inside the function, so what if I have the need to access variables inside the function outside the function? The example above does just that

What does JavaScript you Don’t Know say

— JavaScript you Don’t Know

Closures occur when a function can remember and access its lexical scope, even if the function is executed outside the current lexical scope.

function fun1(){
    var a=0;
    console.log(a);
    return function(){
        a++;
        console.log(a); }}// Notice the result of this call:
varres=fun1(); res(); res(); res(); The output0
1
2
3
Copy the code

instructions

  • The first call to var res=fun1() passes a reference to the anonymous function to the variable res
  • Each time res() is called, the anonymous function is called. Note that the call is made outside the scope of the anonymous function
  • Normally, local variables are collected by garbage collection after the function is executed. However, variable A is not collected after res() is called. Each time res() is executed,a increments
  • The res() function remembers and accesses the original lexical scope

Ok, so the example above clearly shows another use for closures, to access and remember the original lexical scope, so when do we need to access and remember the original lexical scope? I’ll talk about that later

4. To summarize

1. What are closures

A function that can access a variable in another scope and remember the lexical scope in which it is located

2. How to determine is a closure

Closure environments are created when the return value of a function is another function that is executed outside of the original function and accesses the variables of the original function

3. Advantages and disadvantages of closures

  • advantages

    • Implements access to other scope variables and avoids contamination of global variables with their own lexical scope variables

    • The use of global variables can be avoided by keeping local variables (self-scoped variables) in memory holding the value of the last execution and not being collected by the garbage collection mechanism

  • disadvantages

    • Local variables remain in memory and will not be collected, resulting in memory overcrowding and affecting program performance

4. Solutions to closure shortcomings

  • It is recommended to use closures only when absolutely necessary
  • Var a = null; var a = null;

5. Common forms of closures

I have used a number of examples above to explain what a closure is. It is not difficult to find that a closure exists in the form of a function that satisfies the conditions defined by the closure, often in the form of an anonymous function (note: not all anonymous functions are closures, and the two cannot be equivalent).

Form a:

function fun1(){
    return function(){
        // Closure body}}var res=fun1();
res();// Closure function call
Copy the code

Form 2:

(function(i){   
	// Closure body
})(i);// The closure function calls itself
Copy the code

Typical cases of closure application

Avoid variable loss due to inconsistent execution times in asynchronous programs

/ / print 1 to 10
for (var i = 1; i <= 10; i++) {
	setTimeout(function () {
		console.log(i);
	}, 1000);
}
// Result prints 10 11s
Copy the code

Cause analysis:

  • I is declared in the global scope, the anonymous function in the timer is also executed in the global scope, printing I is worth looking for variables layer by layer
  • The for loop is executed much faster than the timer. Therefore, before the timer can print I, the for loop has finished. At this point, the value of I is 11, so the timer prints 11

Solution:

Above example obviously is accessing global variables in an anonymous function, due to the asynchronous failed to print out the accurate causes global variable values, so the solution is to cycle, I use I saved in private scope and kept, using closures

for (var i = 1; i <= 10; i++) {
	(function (j) {
		setTimeout(function () {
			console.log(j);
		}, 1000);
	})(i);
}
Copy the code