First let’s look at ordinary objects and function objects
Let’s look at normal objects and function objects in javascript before we look at prototypes,
As shown in figure 1
- Common objects:
- Most common object: it has the _ _ proto_ attribute. Note: normal objects do not have the prototype attribute! If you call it must return undefined
- Prototype objects: We’ll continue below!
What are common objects in javascript?
// Common objects
function Test() {}var obj1 = new Test();
var obj2 = new Object(a);var obj3 = {};
console.log(typeof obj1); //Object
console.log(typeof obj2); //Object
console.log(typeof obj3); //Object
Copy the code
-
Function object:
-
Anything created with Function() is a Function object. For example: custom functions, event function system Object, Array, Date, String, RegEx are all function objects
_ _ proto_ () == all of the above are instance objects of Function, so only instance objects can have the _ _ proto_ _ attributeCopy the code
-
Function (prototype); Function (prototype); Function (prototype);
In javascript, where are function objects?
// Function object
function F1(){}var F2 = function(){}var F3 = function(a,b){}window.onload=function () {
var div1=document.getElementById('div1');
div1.onclick=function () {
alert(1);
}
console.log(typeof div1.onclick); //function
}
console.log(typeof F1); //function
console.log(typeof F2); //function
console.log(typeof F3); //function
console.log(typeof Object); //function
console.log(typeof Array); //function
console.log(typeof String); //function
console.log(typeof Date); //function
console.log(typeof RegEx); //function
console.log(typeof Function); //function
Copy the code
Function objects are instance objects of Function
Just like Array is created by Function.
ƒ () {[native code]} Array is an instance of Function.
ƒ () {[native code]}
_ _ proto_ === Function. Prototype is true! Returns true
Thus, the following judgment conditions are derived:
Array._ _proto_ _ == Function.prototype //true
String._ _proto_ _ == Function.prototype //true
RegExp._ _proto_ _== Function.prototype //true
Date._ _proto_ _ == Function.prototype //true
Copy the code
ƒ () {[native code]}
Native code means that it comes with the program, which is binary compiled and cannot be displayed. Native code is native code, and here we simply explain it.
The above content as learning prototype before the foreshadowing understanding!! Let’s break down the details of Figure 1 slowly!
Two questions arise
Problem 1 performance
If an object is created in the heap area of memory, a space is created to hold the object, if each object has the same method in it
The problem is that public methods or properties are stored in memory for n copies. , a lot of memory overhead!
As shown in figure 2
Each object generates the same **say()** method, which would take up a lot of memory if every object had the same method in common!
The code for the image above is as follows
function Person(name,age){
this.name=name;
this,age=age;
this.say=function () {
console('Output result'); }}var obj1=new Person();
var obj2=new Person();
var obj3=new Person();
var obj4=new Person();
var obj5=new Person();
Copy the code
Problem 2 Property methods cannot be shared!
Sometimes we want a method that can be used by multiple object types in common!
For example, define an array private method that cannot be accessed by another array object
Code examples:
var arr=[5.5.10];
// sum method of arr array object
arr.sum=function () {
var result=0;
for(var i=0; i<this.length; i++){ result+=this[i];
}
return result;
}
console.log(arr.sum()); // Result: 20
var arr2=[10.10.10];
console.log(arr2.sum()); Uncaught TypeError: arr2.sum is not a function
Copy the code
The sum() method does not exist in arr2. It is a method that is private to arR.
So sometimes we want a method that can be used by multiple objects of the same type in common!
The first problem is that the performance optimization is insufficient, and the second problem is that private methods cannot be called by objects of the same type, so the solution to the above problem is to use: prototype [improve performance] is commonly referred to as: prototype pattern
Now let’s talk about what the prototype is!
What is the prototype object!
According to Figure 1, function objects have a prototype property that points to a prototype object. We can derive the following concepts:
Every function created has a prototype property, which is a pointer to an object.
Prototype object, A.K.A. Constructor, contains a constructor property that points to the current prototype object’s constructor.
The diagram below:
All instances of a particular type will share the properties and methods you define in a prototype object.
The advantage of a prototype object is that it contains properties and methods that can be shared by all instance objects.
The syntactic foundations of prototype objects
For properties and methods of a particular type to be shared by all instances, define them under the prototype object!
To use the ==prototype keyword, write it below the constructor:
// The syntax is as followsConstructor name. Prototype. property = value; Constructor name. Prototype. method =function(){.. Code.. }Copy the code
So with the: constructor name. Prototype you can define properties and methods in your prototype object
Case code:
function createPerson(name,age) {
this.name=name;
this,age=age;
}
createPerson.prototype.say=function () {
console.log('My name is.'+this.name);
}
var a=new createPerson('Joe'.'33');
var b=new createPerson('bill'.'55');
var c=new createPerson('Wang Wu'.'66');
a.say();
b.say();
c.say();
Copy the code
I have drawn a diagram for easy understanding. The flow chart analysis of the above code is as follows:
The special Function of the prototype
Function. Prototype is the exception. Why is it an exception? It should get a prototype object here, but it’s a function object,
As a function object, it has no prototype property. You can see this in Figure 1!
ƒ () {[native code]} please ƒ () {[native code]}
The diagram below:
Prototype knowledge point
To save memory, we put the object’s methods inside the prototype. Why is that?
Overwrite the common methods or properties of an object so that only one copy of the common methods or properties exists in memory
When we instantiate an object with new, all the properties and methods in the constructor are automatically copied in memory and used to assign values to the object. No matter how many times we instantiate, the properties and methods in the prototype are only generated once, so it saves memory.
Priority of common definition versus stereotype definition
The following code:
function createPerson(name,age) {
this.name=name;
this,age=age;
}
createPerson.prototype.say=function () {
console.log('My name is.'+this.name);
}
var a=new createPerson('Joe'.'33');
var b=new createPerson('bill'.'55');
var c=new createPerson('Wang Wu'.'66');
a.say();
b.say();
c.say();
// The normal definition takes precedence over the prototype
c.say=function(){
console.log('output ok');
}
c.say();
Copy the code
So the general definition above takes precedence over the prototype definition! , but this does not override the stereotype, just call normally defined methods first
As shown in figure:
The _ _ proto_ _ in the prototype
To recap, when instantiating new, the system creates an empty object in memory, like var p = {}, copying properties and methods from the constructor into the empty object.
The important thing is that every instantiated object has a _ _ proto_ attribute, which is automatically generated, and the _ _ proto_ attribute points to the protoobject of the class.
The relationship between constructor, instantiated object, and prototype object
Let’s start with a code example
function createPerson(name,age) {
this.name=name;
this,age=age;
}
createPerson.prototype.say=function () {
console.log('My name is.'+this.name);
}
var obj=new createPerson('Joe'.'33');
console.log(obj.__proto__); // Instantiate obj's __proto__ property to get the prototype object
console.log(createPerson.prototype); // The constructor's prototype property can also get the prototype object
console.log(obj.__proto__.constructor); // The constructor in the prototype object gets the constructor
Copy the code
Basic diagram analysis of constructors, instantiated objects, and prototype objects
Of course you can also verify the result by instantiating the object’s _ _ proto_ property and comparing it with the constructor’s Prototype property, which we can print to verify
console.log(instantiate object._ _proto_ _ === constructor. Prototype);//true
Copy the code
Summary of the differences between definitions in examples and definitions in prototypes:
Let’s start with a code example:
function Test(){}// Define attributes
Test.prototype.name = "Zhang";
Test.prototype.age = 33;
// Define the method
Test.prototype.getAge = function(){
return this.age;
}
var t1 = new Test();
var t2 = new Test();
var t3 = new Test();
t3.name = "Bill";
console.log(t1.name); // Joe is from the prototype
console.log(t2.name); // Joe is from the prototype
console.log(t3.name); // Li Si comes from examples
// Print an example to see the result below
console.log(t1);
console.log(t2);
console.log(t3);
Copy the code
The diagram above explains why properties and methods defined in the prototype are common, but properties and methods defined separately in the instance are independent.
So we also infer that defining properties and methods in the instance overrides or implements calls to properties and methods defined in the instance and then looks for them in the prototype if not! This is actually the prototype chain we’ll talk about later!
Detailed understanding of _ _ proto_ _ and prototype
1. All reference types, such as arrays and objects, have a _ _ proto_ _ attribute (also called == implicit prototype ==, which refers to its own prototype object)
Again, all object references have the _ _ proto_ attribute! Remember!
In the following tests, we can see that each of them has a _ _ proto_ attribute in the reference object that they assign
The code is as follows:
function createPerson(name,age) {
this.name=name;
this,age=age;
}
createPerson.prototype.say=function () {
console.log('My name is.'+this.name);
}
var obj=new createPerson('test'.'33');
// Object reference prints
console.log(obj);
var arr=[1.2.3];
// Print array references
console.log(arr);
var arr2=new Array(2.2.2);
// Print array references
console.log(arr2);
Copy the code
**2. Again, note that for all reference types, the _ _ proto_ _ attribute refers to the reference’s own prototype object and the constructor’s prototype attribute is the reference’s prototype object **
So the _ _ proto_ attribute and the constructor’s Prototype attribute are equal to each other in their respective reference types! This can also be shown in the figure above!
The _ _ proto_ attribute and the constructor’s Prototype attribute are compared as follows:
/ / in case 1
function createPerson(name,age) {
this.name=name;
this,age=age;
}
createPerson.prototype.say=function () {
console.log('My name is.'+this.name);
}
var obj=new createPerson('Joe'.'33');
console.log(obj.__proto__); // Prints the prototype object referenced by the obj object
console.log(createPerson.prototype); // Prints out the prototype object for the createPerson constructor
console.log(obj.__proto__===createPerson.prototype); // They are equal and refer to the same prototype object
/ / case 2
var arr=new Array(2.2.2);
console.log(arr.__proto__);
console.log(Array.prototype);
console.log(arr.__proto__ === Array.prototype);
Copy the code
3. All constructors or normal functions have a prototype property (this is also called an explicit prototype, which also points to its prototype object).
Case code:
// A normal function
function Test() {}// Prints the prototype property of a normal function
console.log(Test.prototype);
// constructor
function createPerson(name,age) {
this.name=name;
this,age=age;
}
createPerson.prototype.say=function () {
console.log('My name is.'+this.name);
}
console.log(createPerson.prototype);
Copy the code
The diagram is as follows:
_ _proto _ _ and prototype
==prototype== is an attribute that every function has. It is a pointer to a prototype object that only normal functions or constructors have.
The ==_ proto_ == property is a property supported by mainstream browsers on every reference object except the NULL object that can point to the current reference object: the prototype object is actually the property used to connect the reference object to the prototype
Proto_ proto_ (prototype); proto_ proto_ (prototype);
ƒ () {[native code]} when you call the attribute (_ proto_ _) with a function, you get the following ƒ () {[native code]}
Batch add properties and methods to the prototype
If ==prototype== {if ==prototype== {if ==prototype== {if ==prototype== {if ==prototype== {if ==prototype== {if ==prototype== {if ==prototype== {if ==prototype== {
/ / grammarConstructor. Prototype ={attribute name: value, method name:function(){
// Method body... What is this in this case depends on who called this function when it was executed}, method name:function(){
// Method body... What is this in this case depends on who called this function when it was executed}}Copy the code
Case code:
createPerson.prototype={
aaa:123.// prototype has other properties inside the object
showName:function(){
// What is this depending on who calls the function when it is executed
console.log("My name is :"+this.name);
},
showAge:function(){
// What is this depending on who calls the function when it is executed
console.log("My age is :"+this.age); }}function createPerson(name,age) {
this.name=name;
this.age=age;
}
var obj= new createPerson('Joe'.'33');
console.log(obj);
obj.showName();
obj.showAge();
console.log(obj.aaa);
Copy the code
The above prototype code diagram
Prototype Considerations
== Pay attention to ==
If you customize a constructor and use {} to batch define properties and methods in prototype, you will change the constructor’s direction in the prototype.
Constructor () {constructor () {constructor () {constructor ()
The test code is as follows
function createPerson(name,age) {
this.name=name;
this,age=age;
}
/ * createPerson. Prototype. Say = function () {the console. The log (+ this. 'my name is' name); } * /
createPerson.prototype={
say:function () {
console.log('My name is.'+this.name); }}var obj=new createPerson('Joe'.'33');
console.log(obj.__proto__);
Copy the code
In console output you will see the value _ _proto _ _. The constructor property is gone!
console.log(createPerson.prototype.constructor); ƒ Object() {[native code]}
Copy the code
Prototype basic summary
- Keep a copy of the same method in memory
- The stereotype definition takes lower priority than the normal definition
- Properties and methods that are common throughout the project can be loaded onto the prototype
Core principles of prototype chain
First of all, it should be pointed out that the implementation of inheritance in JS mainly relies on the prototype chain to achieve! That’s why we need to learn how prototype chains work!
Prototype chain core concept
The prototype chain: When you’re trying to call or get a property or method from an instance of an object, if the object doesn’t have the property or method itself meaning that the constructor doesn’t define the property or method you want, The prototype property or method ==(the ‘prototype’ property of its constructor is found in the prototype Object) is returned if it has one, if it doesn’t have one, and if it has one, the top-level Object is returned. Return undefined if still not found! = =
Prototype chain flow chart ==
When the Test constructor has a getName method, there is no need to look for getName in the constructor’s prototype. Instead, look for the getName method in the constructor prototype; If the getName method does not exist in the constructor’s prototype, look for it in the top-level object’s prototype.
The above test case code is as follows:
function Test(name){
this.name=name;
this.getName=function(){
return this.name+"I'm in the constructor.";
}
}
Test.prototype.getName=function(){
return this.name+"I'm in the prototype object.";
}
Object.prototype.getName=function(){
return this.name+"I'm in the top-level object.";
}
var t1=new Test('little red');
console.log(t1.getName());
Copy the code
Prototype chain case code 2 is as follows:
Array.prototype.aaa=123; // Define this custom property under the prototype object
var arr=new Array(1.2.3);
console.log(arr.aaa);
console.log(Array.prototype);
var arr2=['chongqing'.'Shanghai'.'Beijing'];
console.log(arr2.aaa);
Copy the code
The diagram below:
== Summary ==: both ARR and ARR2 can find the aaa attribute, and this attribute is a property of the array prototype object, which is common
You can call this property as long as it’s an array, and the same goes for methods,
So when you create lots and lots of objects of the same type, every object that you create, if it has some common method in it, it takes up a lot of resources,
To do this, you just need to assign values to properties in the constructor and write methods in the Prototype property. Properties can also be written in the prototype.
This way every object reference can use a method or attribute from the Prototype attribute and saves a lot of resources
That’s why we use prototypes!
Schematic summary of overall structure of prototype chain
When you try to call or want a property or method in an object instance, If the Object does not have the property or method, the constructor will use the prototype property to look for the property or method. If the Object does not have the property or method, the constructor will return the property or method. = =
But because the prototype property in the constructor is itself an Object, it also has a _ _ proto_ attribute, so you can go up and get _ _ proto_ _, and get the top-level Object
The diagram below:
Conclusion:
When obj calls test(), JS finds that Fn doesn’t have the method, so it goes to Fn. Prototype. When it does, JS calls Test () in Object.prototype.
This is the prototype chain search, and the layer by layer of links is the prototype chain.
Obj can call methods in Object.prototype because of the prototype chain mechanism!
In addition, when working with prototypes, it is generally recommended to write the methods that need to be extended in the constructor. Prototype property,
And don’t write in the constructor. Prototype. _ _ proto _ _, because here is the Object on top of the Object and definition to the properties and methods All JS object can be called, in this definition more can affect the overall performance, the definition is not recommended to here!