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