preface
About inheritance, how much do you know, what kind of inheritance is the most optimal, let’s learn some knowledge about inheritance, take you to understand their implementation process, as well as their advantages and disadvantages
The relationship between constructor, prototype object, and instance object
Understanding their relationship first helps to understand inheritance better
Prototype chain inheritance
Core: The parent class instance as a subclass prototype code implementation process:
function Parent(name){
this.name = name || 'xt'.this.arr = [1]}function Son(age){
this.age = age
}
Parent.prototype.say = function() { // Define methods that need to be reused and shared on the parent class prototype
console.log('hello');
}
Son.prototype = new Parent()
let s1 = new Son(18)
let s2 = new Son(19)
console.log(s1.say() === s2.say()); //true
console.log(s1.name,s1.age); //xt 18
console.log(s2.name,s2.age); //xt 19
s1.arr.push(2)
console.log(s1.arr,s2.arr); // [1, 2] [1, 2]
Copy the code
Advantages:
- Instance inheritable properties are: constructor properties of the instance, constructor properties of the parent class, and stereotype properties of the parent class. (The new instance does not inherit the attributes of the parent instance!)
Disadvantages:
- Subclass instances share reference properties of the parent constructor, such as the arR property (attributes on stereotypes are shared; if a stereotype property is modified by one instance, the stereotype property is modified by the other!).
- You cannot pass parameters to the parent constructor
Borrow constructor inheritance
Core: To enhance a subclass instance by borrowing the parent class’s constructor is to copy the instance attributes of the parent class to the subclass
Code implementation:
function Parent(name) {
this.name = name;
this.arr = [1].this.say = function() { console.log('hello')}}function Son(name, age) {
Parent.call(this, name) // Copy the instance properties and methods of the parent class
this.age = age
}
let s1 = new Son('XiaoTan'.18)
let s2 = new Son('Ming'.19)
console.log(s1.say === s2.say) // False methods cannot be reused methods are independent, not shared
console.log(s1.name, s1.age); / / XiaoTan 18
console.log(s2.name, s2.age); / / xiao Ming 19
s1.arr.push(2)
console.log(s1.arr, s2.arr); // [1, 2]
Copy the code
Advantages:
- Only the properties of the superclass constructor are inherited, not the properties of the superclass prototype.
- Can inherit multiple constructor properties (call multiple)
- Arguments can be passed to the parent in a child instance.
Disadvantages:
- Only attributes of the parent constructor can be inherited.
- Constructor reuse cannot be implemented. (Call it again every time you use it)
- Each new instance has a bloated copy of the superclass constructor.
Primary inheritance
Core: Wrap an object with a function, and return a call to that function. The function becomes an instance or object that can be added any properties you want
function Parent(name) {
this.name = 'xt';
this.arr = [1]}function object(obj){
function F(){}
F.prototype = obj;
return new F();
}
let s1 = new Parent(object)
s1.name = 'Ming'
s1.arr.push(2)
let s2 = new Parent(object)
console.log(s1.name,s2.name); Xiaoming / / xt
console.log(s1.arr, s2.arr); //[1, 2]
Copy the code
Disadvantages:
- All instances inherit properties from the stereotype and cannot pass parameters
- Reuse cannot be achieved. (New instance attributes are added later)
Parasitic inheritance
Core: On the basis of the original type inheritance, enhance the object, return the constructor
function Parent(name) {
this.name = 'xt';
this.arr = [1]}function object(obj){
function F(){}
F.prototype = obj;
return new F();
}
let Son = new Parent()
function addobject(obj){
var add = object(obj)
add.name = 'white'
return add
}
var s1 = addobject(Son)
console.log(s1.name); / / a small white
Copy the code
Disadvantages:
- No prototype, no reuse.
- The prototype chain inherits multiple instances of reference type attribute pointing to the same, there is the possibility of tampering.
Composite inheritance (composite stereotype chain inheritance and borrowed constructor inheritance)
Core: Inherits the attributes of the parent class and retains the advantages of passing arguments by calling the parent constructor. Then the function reuse is realized by using the parent class instance as the prototype of the subclass.
Code implementation:
function Parent(name) {
this.name = name;
this.arr = [1]
}
Parent.prototype.say = function () { console.log('hello')}function Son(name, age) {
Parent.call(this, name) / / second
this.age = age
}
Parent.prototype = new Son() / / a
let s1 = new Son('XiaoTan'.18)
let s2 = new Son('Ming'.19)
console.log(s1.say === s2.say) // true
console.log(s1.name, s1.age); / / XiaoTan 18
console.log(s2.name, s2.age); / / xiao Ming 19
s1.arr.push(2)
console.log(s1.arr, s2.arr); // [1] [1] does not share reference attributes of the parent class,
Copy the code
Advantages:
- The advantage of preserving constructors is that you can create subclass instances and pass arguments to the superclass constructor.
- The advantage of preserving the prototype chain is that the method of the parent class is defined on the prototype object of the parent class, which can realize method reuse.
- Reference attributes of the parent class are not shared. For example, the ARR attribute
Disadvantages:
- Because the constructor of the parent class was called twice, there is an extra copy of the parent instance attribute
Parasitic combinatorial inheritance
Core: a combination of borrowed constructors for passing parameters and parasitic patterns for inheritance
function Parent(name){
this.name = name || 'xt'.this.arr = [1]}function Son(name,age){
Parent.call(this,name) / / core
this.age = age
}
Parent.prototype.say = function() {
console.log('hello');
}
Son.prototype = Object.create(Parent.prototype) // The core is separated by creating intermediate objects, subclass stereotypes, and superclass stereotypes.
Son.prototype.constructor = Son
let p1 = new Parent()
let s1 = new Son("Little red".18)
let s2 = new Son("Black".19)
console.log(p1.constructor); //[Function: Parent]
console.log(s1.constructor); // [Function: Son]
console.log(s1.say() === s2.say()); //true
console.log(s1.name,s1.age); / / the little red 18
console.log(s2.name,s2.age); / / the little black 19
s1.arr.push(2)
console.log(s1.arr,s2.arr); // [1, 2] [1, 2]
Copy the code
Parasitic combination inheritance can be regarded as the best reference type inheritance
Hope this article can be helpful to you!