Closure in JavaScript

    Apr 18, 2022

    Give the definition of closure in JavaScript and understand it by examples.

    This post was transported from zhihu answer.

    And origin question is:

    In js, when a function is executed, it will be destroyed, and correspondingly, the scope of this function will also be destroyed. The form of closure is to return the function in the function, then use a variable in the global to accept the returned function, because the global variable will not be destroyed, and this variable holds the address of the returned function, so we can use this return function, because as long as there are variables or other things used inside the function, then this function will not be destroyed. So when we use the returned function in the global scope, then the main function will not be destroyed, the scope naturally exists, we can naturally use the variables in the function, and can save the state. I don't know if I understand it this way, right?


    Here is origin answer

    The form of closure is to return the function in the function, then use a variable in the global to accept the returned function, because the global variable will not be destroyed, and this variable holds the address of the returned function, so we can use this return function, because as long as there are variables or other things used inside the function, then this function will not be destroyed. So when we use the returned function in the global scope, then the main function will not be destroyed, the scope naturally exists, we can naturally use the variables in the function, and can save the state.

    What you said is a so long paragraph, so let me first try to break down your understanding, and then analyze it slowly.

    You say

    The form of closure is the return function in the function

    That is wrong. JavaScript was originally designed with functional programming in mind, where functions are first-class citizens in the language. This means that functions can be stored in variables like any other type, passed as arguments to other functions, or returned as function execution values. The function returns a function, which is determined by the language paradigm. Nothing to do with closures.

    So to understand what the form of closure is, we must start with the definition. Its definition is given directly below,

    A closure occurs when a function is executed outside of the lexical scope in which it was defined and can also remember and access the lexical scope in which it was defined.

    According to the above definition, we can know the two characteristics of the closure,

    • First, it executes outside the lexical scope in which it was defined.

    • Second, it also has access to the lexical scope where it was defined.

    It's a bit of a mouthful to say so, so let's give an example to illustrate.

    first example,

    function fpp() {
      var a = 2;
      function bar() {
        console.log(a);
      }
      return bar;
    }
    
    var baz = foo(); // Hey, this is the effect of closure
    

    The lexical scope of the bar function is within the foo function. But if the bar function is called directly outside the foo function, the compiler cannot find the definition of bar outside the foo, and therefore does not recognize bar, and will throw an error, indicating that bar is undefined. So if you want to execute the bar function outside the foo function, you can use bar itself as a return value, let the baz variable outside foo receive the bar function, and then execute it. In this way, the compiler can know that bar is stored in baz after foo is generated, so that the identity of bar is clear: it is a function. It can be executed outside of foo.

    But according to the language setting of JavaScript, when a function is executed, it can access the lexical scope where it is located. For example, functions in the global scope can access global variables. Similarly, when the bar function is declared, it can access the scope where it is located, that is, within the foo function. And the scope in the foo function has a variable a, then this a variable can be directly accessed by the bar function during execution.

    But isn't this about functions returning functions? Then look at the second example

    function foo() {
      var a = 2;
      function baz() {
        console.log(a);
      }
      bar(baz);
    }
    
    function bar(fn) {
      fn();
    }
    

    The bar function is declared outside of foo, baz is defined inside of foo, and the foo function can access bar. Now pass baz to the bar function, and bar will execute it after receiving it. At this time, baz is transferred to the scope execution in bar by passing, and can access a in the original scope, which is a closure. And it doesn't involve the problem of function returning function.

    You see, in the first example above, the **bar function is executed after being stored in the baz variable outside the lexical scope, and can still access the variable a in the lexical scope, which creates a closure.**In the second example, baz is passed to bar through parameters, so that it is executed outside the scope and can access a within the scope. This is also the most essential feature of closures.

    You say

    Because the global variable will not be destroyed, and this variable holds the address of the returned function, so we can use this returned function, because as long as there are variables or other things used inside the function, then this function will not be used destroy.

    You are right in saying that global variables are not destroyed. But I don't understand what you want to say, maybe you want to say, as long as the reference of a function is not destroyed, then this function will not be destroyed? However, in any case, whether the global variable will be destroyed or not has nothing to do with whether the closure will be destroyed...

    In the first example above, baz is defined globally. Stored is a reference to bar. baz will not be destroyed because it is defined globally, and it does not matter that bar and foo will not be destroyed.

    So back to the second example

    function foo() {
      var a = 2;
      function baz() {
        console.log(a);
      }
      bar(baz);
    }
    
    function bar(fn) {
      fn();
    }
    

    The bar function is declared outside of foo, baz is defined inside of foo, and the foo function can access bar. Now pass baz to the bar function, and bar will execute it after receiving it. At this time, baz is transferred to the scope execution in bar by passing, and can access a in the original scope, which is a closure. Here, baz is executed in the scope of bar, not globally, and there is no reference to baz in the global. But this is a closure, so baz won't be destroyed either.

    The closure will not be destroyed, it is determined by the JavaScript interpreter. When the interpreter detects that a closure is generated during execution, the lexical scope where the closure is located will be circled by the interpreter and will never be destroyed. It's not because the closure is referenced globally and will not be destroyed, so the closure will not be destroyed either. It has nothing to do with the global scope.

    Understanding closures is a painstaking process. There are many pitfalls in this regard. The terminology of computer programming is more abstract. Therefore, it is recommended that when you come into contact with a concept, it is best to start with the definition and then contact specific examples, rather than start directly with the examples. **Your sentence "the function returns a function" is most likely influenced by some tutorials on the Internet after directly throwing out examples.

    Hope my answer is helpful to you.