right After 10 months, come back to fill the pit…… I am the dove King

The topic of closures is probably more logical. You can refer to it, but that’s just my idea, or you can do whatever you want. Notice the difference between what I want to expand on and what I want to focus on. (The dividing line is separated)

1. Define what is a closure

An inner function can always access parameters and variables declared in its outer function, even after its outer function has been returned (end-of-life).

(Note: This is a more acceptable definition and can be thrown out at the beginning of the closure issue.)


(Here is an extension of the definition of closure in MDN. If you find it easy to understand, you can also check the relevant materials.)

Closures are functions that have access to free variables.

Here’s an example:

var a = 1;

function foo() {

  console.log(a);

}

foo()
Copy the code

Function foo can access variable a, but a is neither a local variable nor an argument to function foo, so a is a free variable. So foo + foo’s free variable a forms a closure…

The first time I saw this idea was in His article Of Hu Yuba, also check it out. Juejin. Cn/post / 684490…

2. How to generate closures?

As defined, a closure is formed when a function inside a function is used outside the function body.

With regard to the generation of closures, I prefer to illustrate this topic with an example.

Define a function a (name, age, etc.) and assign values to it. Then define a method sayName (name, age, etc.) to print the name, and return the method. We then call the exposed method externally, for example foo=a() and execute foo().Copy the code
This is essentially a closure.Copy the code
function a(){
  this.name = 'a'
  var sayName = function (){
    consule.log(this.name)
  }
  return sayName
}
var b = a()
b()
Copy the code

3. How do closures come about?

I’m going to go back to the example I just gave you. We think, how do closures come about?

(There are two versions, a simple version and an advanced version)


(Simple version)

(The simple version of the explanation I have written before, also have spoken, before writing this language is a little green, write more colloquial.) Juejin. Cn/post / 696175…

(The specific simple version can see the article, here is a brief introduction.)

After a has executed, the garbage collection mechanism will ask if it can completely destroy A’s memory, but A doesn’t know when it will be called again, so a closure object will be created to save the variables that might be called and put them in the heap so that they don’t need to consume any more space on the stack.

When the foo method is actually called, it goes directly to the heap to find the corresponding variable’s storage address.

This completes the function of closures.


(Advanced version)

In fact, the advanced version is more like a specific implementation of a simple version of the operation, is every simple step, is based on what to achieve.

Pre-knowledge (put some big guy links, you can also have a look, I also learn from these places) :

The execution context stack of JavaScript

JavaScript’s scope chain and its implementation

V8 engine garbage collection mechanism

(First look at the article above, Hu Yui talked very well.)

(This is the process of looking at closures from the perspective of the execution context.)

  1. Generate a global context that is pushed onto the execution context stack
  2. Global execution context initialization
  3. Then go global and do specific code execution. Execute to function A, create a context and push it onto the execution context stack.
  4. A context initialization, creating variable objects, scoped chain (a function’s scoped chain property maintenance operation, i.e. operation on A.[[scope]]), this, etc.
  5. After the execution of function A is completed, the execution context of function A is displayed on the execution context stack.
  6. Execute b function, create the execution context of b function, and push the execution context of B function onto the execution context stack
  7. [[scope]], copy the outer scope first, and then press the scope into its own scope to form the scope chain. Based on the scope chain, we can query for the value of a. O, and then save references to related variables), this, and so on in the AO.
  8. When function B completes execution, the context of function B is popped from the execution context stack.
  9. The global execution context pops up from the execution context stack.

(Then some details, mainly how variables are stored in the heap.)

We may wonder, where is the name variable stored in this example? Why is it stored like this?

From the perspective of garbage collection mechanism, in the fifth step, context A is out of the stack. By querying the reference of its variable, it is found that it may be called (closure), so there may be a reference relationship. Therefore, the name variable is stored in the new generation during garbage recycling and is quickly stored in the old generation after being identified by the Scavenge algorithm in the new generation, which is stored in the heap.

Then, as long as this variable has a reference relationship, it can be saved in the old generation and will remain in the heap forever.

On the other hand, we simulate the implementation of scope chain, we can find that when calling b function, we can find the value of A. O, which stores the reference to the variable name, so we can realize the call to the variable.

4. Closure applications

Knowing what a closure is, it is natural to think of applications for closures.

Closures implement a protection mechanism that keeps variables from being destroyed. And closures make these variables private (which can only be called by thrown internal methods) instead of a global variable.

Note: Closures are “protective” : Protect private variables from the outside interference (in real project, especially the team collaborative development, should as far as possible to reduce the use of global variables, prevent conflict between each other (” global variable pollution “)), so this time we can this part of herself wrapped in a closure, let global variables into private variables.


The singleton application

Var createLogin = function(a,b,c){console.log(a,b,c); 1,2,3 var div = document.createelement ('div') div.innerhtml = 'I am login popover' div.style.display = 'none' document.body.appendChild(div) return div } var getSingle = function (fn) { var result; Return function () {/ / return a function inside the form closure / / if the result using executed only once, otherwise you will return the result | | (result = fn. Apply (this, the arguments))} } var create = getSingle(createLogin) document.getElementById('loginBtn').onclick = function (){ var loginLay = Create (1,2,3) loginlay.style. display = 'block'}Copy the code

Image stabilization function

The event handler executes once if the event has not been triggered for a certain period of time. If the event is triggered again before the set time, the delay starts again.

** Trigger event within a period of time, another trigger event, restart delay, on behalf of the restart timer. Within the set time, the event restart delay is triggered again, which represents the restart timer, which means that the last time has not ended the timer needs to be cleared and start again.

// If the operation is repeated within a certain period of time, the operation will only refresh the read bar, and wait until the last operation timing execution. function mydebounce(fun, delay) { let timer; return function (args) { let that = this; clearTimeout(timer); // We should store the timer variable. // The timer variable needs to be kept in memory. // Since you don't want to print the result that has been entered before, Timer = setTimeout(function () {fun.call(that, args); }, delay); }; }Copy the code

Throttling function

Ensure that event handlers are called only once in a period of time when firing continuously.

Function mythrottle(fun, delay) {let pre = 0; return function (... Args) {let now = date.now (); let now = date.now (); if (now - pre > delay) { pre = now; fn.apply(this, args); }}; }Copy the code

5. Lead the conversation after closing

As you can see from the whole process, after a brief introduction to closures, we can lead the topic to scope, scope chain, execution context, precompilation, V8 engine recycling mechanism, JS code compilation and execution, this pointing, and so on.


Make a friend

Currently, I am crazy about learning front-end knowledge and want to become a better front-end engineer, so I like to record and share my study notes. How my knowledge reserve is limited, can only output some of their own ideas.

But!!! I really took lots and lots of notes (indeed many notes are excerpted, so it is not kind to post as my own….) , I also really hope to share more knowledge points with like-minded partners!

Therefore, I simply set up a blog of my own, hoping to get to know more friends, if you are interested, please come to my blog ~ The diary of Amin’s growth