In depth JS Foundation
prototype
prototype
Definition: the prototype is an attribute of the function object, which defines the common ancestor of the object created by the constructor. The object generated by the constructor can inherit the properties and methods of the prototype. Prototypes are also objects.
Is the father of the function. You can set properties to the function
- Each function has a prototype attribute, which points to an object null object (i.e. prototype object) by default.
- There is a property constructor in the prototype object, which points to the function object
Implicit prototype__ proto__
Object__ proto__ Attribute: automatically added when creating an object. Internal code. The default value (pointing value) is the prototype of the constructor
Person.prototype.name = "sunny"; function Person(){ //var this = {__proto__:Person.prototype} } var person = new Person(); Person.prototype = { name : "cherry" } console.log(person.name); //Note that the result here is "sunny" instead of "cherry" /*Because when new an object, the function is executed, and the default value in the function is__ proto__ Point to prototype Next, execute person prototype={name:"cherry"} Here is only to modify the value of prototype, but__ proto__ It has already been defined in the function to point to sunny*/
Can be understood as prototype and__ proto__ There are different
Connection between the two
Explicit and implicit are displayed in functions in different objects and implicit in objects, but they can be called by pointing to the same address. This is the principle of calling function methods.
//Constructor function Fn(){ } //1. Each function has a prototype, which points to an empty object by default console.log(Fn.prototype); //2. Each instance object has one__ proto__, // Create instance object var fn = new Fn();// this.__proto__ = Fn.prototype // The value of the implicit prototype of an object is the value of the explicit prototype of its corresponding constructor console.log(Fn.prototype === fn.__proto__);//true // Add method to prototype Fn.prototype.text = function () { console.log('1'); } // Call the method of the prototype through an instance fn.text();
Prototype chain
The prototype is connected with the previous prototype, and the terminal is finally found
//Access object prototype.__ proto__ Get null, indicating that this is the terminal Grand.prototype.lastName = "Deng"; function Grand(){ this.name = "daming"; } var grand = new Grand(); Father.prototype = grand;//grand is the prototype of the constructor Father function Father(){ this.name = "xiaoming"; } var father = new Father(); function Son(){ this.name = "xiaoxiaoming"; } Son.prototype = father;//father is the prototype of the constructor Son var son = new Son(); console.log(son.lastName); /*This is accessed through the prototype chain, son-->son.__proto__(Namely father) -->father.__proto__(Namely grand)-->grand.__proto__,lastName
call/apply
Function: change the direction of this
function Person(name,age) { this.name = name this.age = age } var person = new Person('c',100); var obj = { } Person.call(obj,'jc',90) // Obj is also passed into person, and this = obj, which means borrowing other people's methods to generate attributes. Does not affect the original function, person or w 100 console.log(obj); //Borrow other people's functions to realize their own functions function Person(name,age,sex){ this.name = name; this.age = age; this.sex = sex; } function Student(name,age,sex,tel,grade){ Person.call(this,name,age,sex); this.tel = tel; this.grade = grade; }
closure
About closure
Generally speaking, local variables only act on local variables, and local variables inside the function cannot be read outside the function. Sometimes local variables inside a function are needed, and a workaround method is needed, that is, another function is defined inside the function
function f1(){ var n=999; function f2(){ alert(n); // 999 } }
In the above code, function f2 is included in function f1. At this time, all local variables in f1 are visible to f2.
But not the other way around. The local variables inside f2 are invisible to f1. This is the unique "chained scope" structure of JavaScript language.
Since f2 can read the local variables in f1, we can read its internal variables outside f1 as long as f2 is taken as the return value.
At this time, function f2 is a closure, which can be understood as a bridge between the inside and outside of the function.
In essence, a closure is a function inside a function. By returning the child function and calling it externally, the local variables of the parent function are activated, that is, the stack area where the function is located is still retained.
For the well-known mainstream languages, such as C and java, as long as return is executed inside the function, the function will return the result, and then delete the area where the function is located in memory. The life cycle stops. The same is true for general js functions.
However, js functions with closure feature are a little special. After return, although the f1 function is cleared, f2 is returned and retained. The stack area of f1 and f2 in memory, that is, local variables, will be retained. The stack area can be continuously modified externally and will be retained because f2 always exists. This creates a closure.
be careful:
- Closures are generated when internal functions are saved externally. Closure will cause the original scope chain not to be released, resulting in memory leakage. A leak is when memory is consumed.
- Closure will change the value of the internal variable of the parent function outside the parent function. Therefore, if you use the parent function as an object, the closure as its Public Method, and the internal variable as its private value, you must be careful not to change the value of the internal variable of the parent function.
Execute function now
This kind of function is not declared and is released after one execution. It is suitable for initialization.
(function(a,b,c){ console.log(a+b+c); }(1,2,3))
effect
- Public variable implementation
//Function accumulator function add(){ var count = 0; function demo(){ count ++ ; console.log(count); } return demo; } var counter = add(); counter(); counter(); counter(); counter();
- Can be used as cache (storage structure)
// 1. function test(){ var num = 100 function a(){ num ++ console.log(num); } function b(){ num -- console.log(num); } return [a,b] } var myArr = test(); myArr[0]();//101 myArr[1]();//100 // 2. function eater(){ var food = "apple" var obj = { eat :function(){ console.log('eating'+ food); food = "" }, push : function(myfood){ food = myfood; } } return obj } var eater1 = eater() eater1.push('banana') eater1.eat(); // Eliminate the impact of closures // Purpose: output 1-10 function test(){ var arr = [] for(var i = 0;i<10;i++){ arr[i] = function(){ console.log(i); } } return arr; } // The stack created by array arr is unique. i has become 10 in the loop, and the stack corresponding to the subset is also the same, forming one // For the case of ten, that is, 10 objects in a space are used together, so it will be the last to change the value of the stack var myArr = test() for(var j = 0;i<10;j++){ myArr[j](); //Output 10 10 } // Solution 👇 function test(){ var arr = [] for(var i = 0;i<10;i++){ (function(j){ arr[j] = function(){ console.log(j); } }(i)) } return arr; } // Turn each memory into an immediate execution function, constantly update the incoming parameters, and destroy them after use. There is no cumulative cache problem, and it becomes one-to-one
-
Encapsulation and property privatization can be realized (supplemented later)
-
Model development to prevent pollution of global variables (later supplement)
Packaging
Give the original value a new attribute without reporting an error, but the result is undefined or null. The reason is that the computer has done a process of wrapping classes
var num = 4; num.len = 3; /*Implicitly, the following process occurs to make up for your shortcomings: new Number(4).len=3 That is, first create a digital object to store the original value, and then add an attribute len=3; But the next step after execution is to destroy the delete */ console.log(num.len); //This is to access num.len, so new number (4) occurs again Len, but the len here is different from the above. It is undefined var str = 'abc' str +=1 var test = typeof(str);//test = 'string' if(test.length == 6){ test.sign = '123' } console.log(test.sign); //Print out undefined