Prototype and inheritance comprehensive analysis
1. What is a prototype, prototype chain
A prototype is an object called Prototype.
In JS, every data type is an object, even simple data types such as number and string are instantiated by number and string constructors.
Each of these instance objects has a __proto__ property of its own, which holds (typically) a reference to its constructor prototype.
A function is also an object, but it can be used as a constructor to generate instance objects. It is special in that it has a Prototype in addition to __proto__ and that Prototype is the main character
Start by writing a constructor:
function Foo(){}
Copy the code
Here Foo is our constructor, and it’s declared to do two big things inside the compiler.
- Takes up space in the heap memory as the storage address of the constructor
- It takes up a chunk of heap memory for this constructor prototype
Prototype
Storage address of - Properties in the constructor
Prototype
Refers to the prototype address in 2, and the prototype object also has a name calledconstructor
The attribute of the. That is, the constructor object and its prototype object are like a bidirectional linked list (note that sometimes we specify new prototype objects, be sure to associate them with constructors).
After the new Foo ()
Know what New does:
- Create memory space for this new instance object
- Point the constructor’s this to the new instance object
- Of the new instance object
__proto__
The prototype object pointing to the constructor - Execute the logic inside the constructor, where there is no return, and the constructor will create the new instance as well
So what is a prototype chain?
The prototype object of the Foo constructor above is itself an object. That is, a prototype that has __proto__ pointing to its constructor, the constructor of an Object called Object. Object is an Object, so __proto__ is also an Object, but then __proto__ is null.
This chain is called a prototype chain.
2. Some operations on the prototype
2.1 Prototype detection
instanceof
The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object
Through chestnuts
isPrototype
The isPrototypeOf() method tests whether an object exists on the prototype chain of another object.
As shown below, Objec’s prototype appears in Foo’s prototype chain
2.2 Detecting object properties
in
Will look for the prototype chain
hasOwnProperty
Only look at itself
2.3 Setting prototypes
2.3.1 Object.create
The object.create method creates a new Object with a prototype that can be specified for the new Object.
Create a new object and prototype it to Foo
2.3.2 __proto__
__proto__ can of course change the prototype of an object, but there are a few things to note here
__proto__
It is not an object property per se, but can be thought of as one when accessing the prototype objectgetter/setter
, its value is only allowed to be object or NULL- although
__proto__
Stereotypes can be obtained and set, but are generally not recommended for stereotype Settings. There are dedicated apis below
2.3.3 SetPrototypeOf and getProttoeypOf
2.3.4 Last note
3. The inheritance
class
After ES6, JS added the class syntax.
class A {
constructor(x) {
this.x = x;
}
sayHello() {
console.log(`hello The ${this.x}`); }}class B extends A {
constructor(x) {
super(x)
}
}
const b = new B('b');
b.sayHello()
Copy the code
This allows us to write inheritance in JS in the same way we write Java. But note that while it can now be written this way, the nature of its implementation inheritance remains the same. The core of inheritance is still the stereotype, and class is just a syntactic sugar.
Return to the
function A(x) {
this.x = x;
}
A.prototype.sayHello = function() {
console.log(`hello The ${this.x}`);
}
function B(x) {
A.call(this, x);
}
B.prototype.__proto__ = A.prototype;
const b = new B('b')
b.sayHello();
Copy the code
Why are properties in constructors and methods in prototype objects
Note that when we instantiate a new object, we primarily perform constructors. For example, put some properties from the constructor into a new object. X as above. If you add more methods to it, you’ll need to store their references in the new object and open up memory to store their entities. So we have one more of these operations for each new one. So many duplicate methods waste space and are not reusable.
4. 7. Smart refrigerator
4.1 Inheritance of prototype chain
Principle: Sets the instance object of the parent class to be the prototype of the subclass
function A(){}
function B(){}
B.prototype = new A();
Copy the code
Pros: Simplicity
Disadvantages: resets the prototype object of B but does not have an echo, so the constructor B is not available. And the instance property of A becomes the stereotype property of B
4.2 Borrowing constructors
How it works: A subclass constructor calls a parent class constructor
function A(x){
this.x=x;
}
function B(x){
A.call(this,x);
}
Copy the code
Advantages: Can pass arguments to the parent class
Cons: everything is written in constructors, function reuse is out of the question.
4.3 Combination Inheritance
Principle: 4.1 + 4.2
function A(x){
this.x=x;
}
function B(x){
A.call(this,x);
}
B.prototype=new A();
B.prototype.constructor =B;
Copy the code
Advantages: that is to achieve method reuse and can be passed to the parent class value
Disadvantages: Constructor A is called twice
4.4 Original type inheritance
How it works: Set a function in which a new constructor is created, and the argument to the function is the prototype of the inner constructor. Finally, the constructor instance is returned
function object(o){
function A(){};
A.prototype=o;
return new A();
}
Copy the code
This function is object.create ()
Cons: Review 4.1
4.5 Parasitic inheritance
Idea: 4.4 + make another function that encapsulates the inheritance process
// Parasitic inheritance
function obj(o) {
function Foo() {};
Foo.prototype = o;
return new Foo();
}
function createAnoter(o) {
let clone = obj(o)
clone.sayHi = function() {};
return clone;
}
Copy the code
Pros and cons: refer to 4.2
4.6 Parasitic combinatorial inheritance
The idea is to implement a extend that completes the link of the prototype chain and the chain back of the prototype and constructor
// Parasitic combinatorial inheritance
function extend(fa, son) {
son.prototype = Object.create(fa.prototype);
son.prototype.constructor = son
}
function Fa(name) {
this.name = name;
}
function Son(name, age) {
Fa.call(this, name, age)
}
extend(Fa, Son)
Copy the code
Pros and cons: Refer to 4.3. What is slightly better than 4.3 is that the superclass constructor is called only once
4.7 Es6
An example is given in section 3