1, Closure
- What closures are, how closures are generated, and the functions of closures are explained one by one below
1) The classic use of closures. The following code implements three buttons. When you click which button, the prompt is the corresponding button. However, in the following code, no matter which button you click, the output result is the fourth, because when you click the button, the loop has been executed, i==3, and then the result is the fourth.
var btns = document.getElementsByTagName('button') //Traversal plus listening for (var i = 0,length=btns.length; i < length; i++) { var btn = btns[i] btn.onclick = function () { alert('The first'+(i+1)+'individual') } }
This problem can be solved after using closures (of course, there are other ways to solve it, such as declaring i with let or saving the corresponding i)
//Using closures for (var i = 0,length=btns.length; i < length; i++) { (function (j) { var btn = btns[j] btn.onclick = function () { alert('The first'+(j+1)+'individual') } })(i) }
-Understanding closures (generation of closures)
Closures are generated when nested functions refer to variables of external functions.
function fn1 () { var a = 2 var b = 'abc' function fn2 () { //Executing the function definition will produce closures (without calling internal functions) console.log(a) } // fn2() } fn1()
- Function of closure
1) After the function is executed, the internal variables will not be destroyed, but will always exist
2) Variables inside a function can be manipulated outside the function
function fn1() { var a = 2 function fn2() { a++ console.log(a) } return fn2 } var f = fn1() f() // 3 f() // 4
- Common closures
1) Take a function as the return value of another function
2) Pass a function as an argument to another function call
// 1. Take the function as the return value of another function function fn1() { var a = 2 function fn2() { a++ console.log(a) } return fn2 } var f = fn1() f() // 3 f() // 4 // 2. Pass a function as an argument to another function call function showDelay(msg, time) { setTimeout(function () { alert(msg)// Generate closures and msg without time }, time) } showDelay('atguigu', 2000)
- Closure lifecycle
1) Generate: generated when the internal function definition is executed (no need to call)
2) Death: when an internal function becomes a garbage object
function fn1() { //At this point, the closure has been generated (function promotion, internal function object has been created) var a = 2 function fn2 () { a++ console.log(a) } return fn2 } var f = fn1() f() // 3 f() // 4 f = null //Closure death (function objects containing closures become garbage objects)
-Shortcomings and solutions of closures
Disadvantages: because the variables inside the function are saved and not destroyed, it occupies memory and is easy to leak memory.
Solution: when the variable is useless, destroy the variable to free memory.
In the previous step, the code said how to destroy the variables in the closure
- Explain memory overflow and memory leak
1) Memory overflow: similar to the water cup in life, the space of the water cup is only so large. When you pour water greater than the capacity of the water cup, it will flow out. Similarly, memory is also. When the memory occupied by your running program is greater than the rest of your memory, it will overflow and the program will not run. (for example, if you create an array with a length of 10000 for 100000 times or more, your computer will overflow)
2) Memory leak: originally, I wanted to create a local variable inside the function, which will be automatically destroyed after the function is executed. However, a=2 directly becomes an unexpected global variable, which has occupied memory all the time. After more such behaviors, the memory will be slowly exposed, the runnable memory will become less, and there will be memory overflow.
Common memory leaks:
1. Unexpected global variable
2. Timer or callback function not cleared in time
3. Closure
// Memory leak // Unexpected global variable function fn() { a = new Array(10) console.log(a) } fn() // Timers or callback functions that are not cleaned up in time var intervalId = setInterval(function () { //Do not clean after starting the cycle timer console.log('----') }, 1000) // clearInterval(intervalId) // closure function fn1() { var a = 4 function fn2() { console.log(++a) } return fn2 } var f = fn1() f() // f = null
- Test questions
Question 1:
//Code snippet 1 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); // the window
After object.getNameFunc() is executed, it returns the function(){return this.name;}; Then execute the internal function. At this time, it is necessary to distinguish who is executing the function later. This is who, obviously window
Question 2:
//Code snippet 2 var name2 = "The Window"; var object2 = { name2 : "My Object", getNameFunc : function(){ var that = this;// Assign the object2 object address to that return function(){ return that.name2; }; } }; alert(object2.getNameFunc()()); // my object
Question 3:
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n) } } } var a = fun(0)//undefined a.fun(1) // 0 a.fun(2) // 0 a.fun(3) // 0 var b = fun(0).fun(1).fun(2).fun(3) // undefined // 0 // 1 // 2 var c = fun(0).fun(1) //undefined 0 c.fun(2) // 1 c.fun(3) // 1
This question mainly depends on whether to create a new closure
2, Object advanced composite inheritance
- Combined inheritance of prototype chain + borrowing constructor
1) Using prototype chain to realize method inheritance of parent type object
2) Use super() to borrow the parent type to build the function to initialize the same attribute
function Person(name, age) { this.name = name this.age = age } Person.prototype.setName = function (name) { this.name = name } function Student(name, age, price) { Person.call(this, name, age) // In order to get the attribute, modify this point this.price = price } Student.prototype = new Person() // In order to see the methods of the parent type Student.prototype.constructor = Student //Fixed constructor property Student.prototype.setPrice = function (price) { this.price = price } var s = new Student('Tom', 24, 15000) s.setName('Bob') s.setPrice(16000) console.log(s.name, s.age, s.price)
The following is an illustration of the implementation