The introduction

On the Internet a lot of articles about the scope and closures, their understanding of the pure theoretical knowledge is not quickly, but his pictures have very strong memory and comprehension, so decided to show the knowledge of the knowledge point to the picture, deepen their understanding and if you can help to the children’s shoes are studying is the better

Let me tell you about this in terms of the entire life cycle of a function

Function life cycle

Let’s start with some sample code

var a = 10;
function func(a) {
  var a = 20;
  a++;
  console.log(a);
}
func();
console.log(a);
Copy the code

Before executing the program

  1. First, create an ECS, which is an array that holds the execution environment of the function being called, or an object.

  2. Then add main, the execution environment for the browser’s main program, to the ECS

  3. Create the global scope object Window

  4. The main execution environment references window

When you define a function

  1. Global variables of primitive types are stored directly in the Window environment. Since functions are reference types, global variables are first declared by function names

  2. The function object is then created to encapsulate the function definition

  3. The scope attribute of a function object refers to the scope in which the function was created. This means that when a function is executed, it will go back to the scope in which it was created to find the variable if the function itself does not provide enough variables for the function to execute completely.

  4. The function name is followed by an address to the function object

Reference types can only store addresses, which are explained in detail in this note on value passing

Function call

  1. Push the execution environment element for this function call into the ECS

  2. Create the function scope object (AO) used in this function call, which is the temporary scope

  3. Create and store all local variables in the AO, including parameters and variables declared with var in functions

  4. Set the PARENT property of the AO and the scope property of the reference function to point to the parent scope object

  5. The execution environment of the function refers to the AO

  6. Follow the arrow, look for variables in the AO, local variables, if not in the AO, then follow the arrow to the parent scope

After the function call

The execution environment of the function is removed from the stack, the AO is released, and local variables in the AO are also released.

When we learned the whole result, it became clear that the results of the two consoles would also agree.

closure

As mentioned earlier, global variables are reusable but pollute the world, while local variables do not pollute the world but are not reusable.

I personally think of closures as a mechanism for reusing variables and protecting them from contamination, which is a solution to this situation.

The characteristics of

The outer function that wraps the protected variable and the inner function that operates on the variable

The outer function returns the object of the inner function

  • return function(){.. }
  • Assign an inner to a global variable directlyfunction
  • Store internal functions in an object’s property or array elementreturn [function function function]return {fun:function(){... }}

Call the outer function, enclosing the returned inner function object with the outer variable, forming a closure.

The principle of

Post the sample code first

function outer() {
  var num = 1;
  return function() {
    console.log(num++);
  };
}

var getNum = outer();
getNum();
getNum();
num = 1;
getNum();
Copy the code

Let me draw the principle of closure formation using the drawing tool

The outer name is stored in the window and refers to the outer function object. GetNum also stores the variable name in the window because it was declared in advance.

GetNum = outer() creates outer and assigns getNum.

Var num = 1; var num = 1; , all have said before, but many repeat.

Create an anonymous function, getNum points to an anonymous function object, and the scope of the anonymous object points to its parent scope, outer’s scope. The Outer’s AO should have left as well, but because of the powerful triangle, it was forced to hold it back, creating what is called a closure.

The reason for closures is that the outer function’s scoped object cannot be released

GetNum =outer()getNum is just a function

Calling getNum() creates a temporary scope for getNum. GetNum is an anonymous function in outer, so its parent points to the scope left by outer. When console.log(num++) is executed and num is not in his scope, he follows the chain of scopes and finds num in outer’s scope and autoappends it. So the next time getNum is called num will start at 2, not 1.

Num is not a global variable, and we implement repeated calls to num. That’s what closures are for.

Setting num = 1 simply adds the value of num to the window object, The next time getNum is called, the js engine will start from getNum scope and search for num along the scope chain. The outerAO will find num, so num in the window will not be affected at all. So the output of this code is 1, 2, 3.

disadvantages

Closures do have their drawbacks, of course

  • It takes up more memory than normal functions because the scoped object (AO) of the outer function always exists

  • Prone to memory leaks

The solution

Reset external variables that reference in-memory function objects to NULL

getNum = null;
Copy the code

The getNum line to outer will break, the triangulation will break, and both the function object and outerAO will be destroyed.

If you think the article is good, please give a star to encourage gayhub