Closures are a mechanism for function execution

Closure mechanism:

The two main mechanisms created by our function execution are “save/protect”, called closure mechanisms!!

[Protection] : Protect the private variables inside from external interference. Prevent contamination of global variables

[Save] : Once the context forming non-destructible scope is not released, its private variables and values are saved and available for retrieval in their “lower” contexts

1. The application of closures in actual combat

[1] The protection of private variables in closures

[jquery] Add attributes to the global window

Function (){function jquery(){} })() when used: jquery() or $()Copy the code

Zepto returns the result of a self-executing function in a variable

var zepto=(function(){ return { fn:function(){}, ..... }})() // when in use: zepto.fnCopy the code

[2] The saving mechanism of private variables – TAB case recall,

【 TAB case original 】

There’s a couple of different versions of poke here and poke here

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, "> <meta http-equiv=" x-UA-compatible "content="ie=edge"> <title>Document</title> <style> * {margin: 0; padding: 0; } ul, ol { list-style: none; } .main { width: 500px; margin: 0 auto; } ul>li { width: 100px; height: 40px; line-height: 40px; text-align: center; border: 1px solid #333; margin-right: 10px; display: inline-block; position: relative; top: 1px; } .main>div { height: 300px; line-height: 300px; border: 1px solid #333; text-align: center; display: none; } .main li.current { background: darkcyan; border-bottom-color: darkcyan; } .main div.current { background: darkcyan; display: block; } < / style > < / head > < body > < div class = "main" id = "main" > < ul > < li class = "current" > music < / li > < li > TV < / li > < li > variety < / li > < / ul > <div class="current"> Music content </div> <div> TV content </div> <div> Variety content </div> </div> </body> </ HTML > <script> var main = document.getElementById("main"); var lis = main.getElementsByTagName("li"); var divs = main.getElementsByTagName("div"); for (var i = 0; i < lis.length; i++) { lis[i].index = i; lis[i].onclick = function () { var index = this.index; change(index); } } function change(index) { for (var i = 0; i < lis.length; i++) { lis[i].className = ""; divs[i].className = ""; } lis[index].className = "current"; divs[index].className = "current"; } </script>Copy the code

2, recall the original inside I why is 3

1. [Thinking in scope mode]

When we trigger the click event, the function, form a private context, in this private context, not the private variable I, to the superior to lookup context, so at this point the superior function, is in the global context of I, when we click the event, the for loop already completed, I would have is 3

Context:

  • Window global context EC(G)
  • Function execution forms a private context
for (var i = 0; i < lis.length; I ++) {lis[I]. Onclick = function () { When we trigger the click event, the function, form the private context, / / in this private context, and have no private variable I, to the superior to lookup context, so at this point the superior context is a global / / and global role up and down the inside of the I, when we click on time, at this time for loop already completed, I was already 3 change(I); }}Copy the code

2, [synchronous asynchronous events to think]

  • Synchronous event: When an event is done, move on to the next event
  • [Asynchronous event] : When an event has not been completed, no longer wait, go to the next event. All events are programmed asynchronously.
for (var i = 0; i < lis.length; i++) { lis[i].onclick = function () { change(i); }}Copy the code

The for loop is a synchronous event and I =3; Click events are asynchronous events, and by the time we click the button on the page, the for loop has already finished executing.

lis[0].onclick = function () {
            change(i);
}

lis[1].onclick = function () {
            change(i);
}
lis[2].onclick = function () {
            change(i);
}
Copy the code

Solution: Refer to the TAB solution in the TAB file

exercises

let x = 5; const fn = function fn(x) { return function (y) { console.log(y + (++x)); }}; let f = fn(6); f(7); fn(8)(9); f(10); console.log(x);Copy the code

Browser garbage collection (GC)

Heap memory release mechanism

Tag clearance [Google]

  • If the hexadecimal address of the current heap is referenced by something else, the heap cannot be freed.
  • If nothing occupies the heap, the browser “reclaims/frees” the unreferenced heap when it is idle
Let obj={name:'zhufeng'} //obj=null; // let obj not point to the object's heap memory; Then the above objects can be freed from the heap.Copy the code

Stack memory (execution context) release mechanism

  • The global context is created when the page is loaded and released only when the page is closed
    • Refreshing the page releases the global context and regenerates a new global context
  • Private context (whether function private context or block-level context)
    • In general, the stack is released after execution to optimize stack memory
    • Special case: if an object created in the current context is occupied by something other than the context, then not only the object created cannot be freed, but also the private context associated with it cannot be freed!!
      • Doing so will consume memory.
      • Because it is not released, everything in this private context is retained and can be used later

thinking

Can the following code output 0, 1, 2, 3, 4, 5 every 1000MS?

If not, why?

And how to solve it?

/ / no: // The first round of the loop global I =0 set the first timer {1000} the callback function set to the timer is not executed, wait 1 second to execute, the loop continues // the second round of the loop global I =1 set the second timer {2000} //... Var I = 0; var I = 0; var I = 0; var I = 0; i < 5; i++) { setTimeout(function () { /! EC (AN) * * * * scope chain: < EC (AN), EC (G) > * parameter assignment: - * variables: - *! / console.log(i); }, (I + 1 * 1000);}, (I + 1 * 1000); }Copy the code

The solution is as follows

Use closures to address saved applications

Self-executing function

End of loop: set up five closures, each closure has its own private variable “I”, store the value of 0~4; Global I is 5;

for (var i = 0; i < 5; I ++) {function (I) {setTimeout(function () {console.log(I); }, (i + 1) * 1000); })(i) }Copy the code

A large function returns a manually generated closure from a small function

 var fn=function(i){
            return function () {
             console.log(i)
        }}
 for (var i = 0; i < 5; i++) {
        setTimeout(fn(i), (i + 1) * 1000);
  }
Copy the code

Use the forEach

// new Array(5).fill(null) creates an Array of length 5 and fills each item with null to make it a dense Array so that it can be used as a parameter placeholder. New Array(5).fill(null).foreach (function (_, Index) {// EC(AN1) index=0 set timer {1000} closure // EC(AN2) index=1 set timer {2000} closure //... setTimeout(function () { console.log(index); }, (index + 1) * 1000); });Copy the code

Real projects use lets

for (let i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, (i + 1) * 1000);
}
Copy the code

Final solution: Timer parameter passing “Core: Closure”

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