First, prototype chain inheritance

Use an instance of a parent class as a prototype for a subclass

function Parent() {
   this.isShow = true
   this.info = {
       name: "yhd".age: 18}; } Parent.prototype.getInfo =function() {
   console.log(this.info);
   console.log(this.isShow); // true
}

function Child() {};
Child.prototype = new Parent();

let Child1 = new Child();
Child1.info.gender = "Male";
Child1.getInfo();  // {name: "yhd", age: 18, gender: "male "}

let child2 = new Child();
child2.getInfo();  // {name: "yhd", age: 18, gender: "male "}
child2.isShow = false

console.log(child2.isShow); // false
Copy the code

Advantages:

1. Superclass methods can be reused

Disadvantages:

  1. All reference attributes (info) of the parent class are shared by all subclasses. Changing a reference attribute of one subclass affects the other subclasses as well
  2. Subtype instances cannot pass arguments to parent type constructors

Constructor inheritance

The call() and apply() methods can be used in the subclass constructor to call the superclass constructor

function Parent() {
  this.info = {
    name: "yhd".age: 19,}}function Child() {
    Parent.call(this)}let child1 = new Child();
child1.info.gender = "Male";
console.log(child1.info); // {name: "yhd", age: 19, gender: "male "};

let child2 = new Child();
console.log(child2.info); // {name: "yhd", age: 19}
Copy the code

By using the call() or apply() methods, the Parent constructor is executed in the context of a new object created for the Child instance, which is equivalent to running all the initialization code in the Parent() function on the new Child instance object, resulting in each instance having its own info attribute.

1. Pass parameters

One advantage of a stolen constructor over stereotype chain inheritance is that arguments can be passed in the subclass constructor as in the superclass constructor.

function Parent(name) {
    this.info = { name: name };
}
function Child(name) {
    // inherits from Parent and passes the parameter
    Parent.call(this, name);
    
     // Instance properties
    this.age = 18
}

let child1 = new Child("yhd");
console.log(child1.info.name); // "yhd"
console.log(child1.age); / / 18

let child2 = new Child("wxb");
console.log(child2.info.name); // "wxb"
console.log(child2.age); / / 18
Copy the code

In the example above, the Parent constructor takes a name argument and assigns it to an attribute. Passing this argument when the Parent constructor is called in the Child constructor actually defines the name attribute on the Child instance. To ensure that the Parent constructor does not override attributes defined by the Child, you can add additional attributes to the subclass instance after calling the Parent constructor

Advantages:

  1. Arguments can be passed to the parent class in the subclass constructor
  2. Reference properties of the parent class are not shared

Disadvantages:

  1. Subclasses do not have access to methods defined on Parent class prototypes (that is, methods defined on Parent. Prototype), so all method properties are written in constructors that are initialized each time an instance is created

3. Combinatorial inheritance

Composite inheritance combines the advantages of stereotype chain inheritance and embeded constructor inheritance (constructor inheritance),

The basic idea is to use a stereotype chain to inherit properties and methods from the stereotype and a constructor to inherit instance properties, so that methods can be defined on the stereotype for reuse and each instance can have its own properties

function Parent(name) {
   this.name = name
   this.colors = ["red"."blue"."yellow"]
}
Parent.prototype.sayName = function () {
   console.log(this.name);
}

function Child(name, age) {
   // Inherits the superclass attributes
   Parent.call(this, name)
   this.age = age;
}
// Inherits the parent method
Child.prototype = new Parent();

Child.prototype.sayAge = function () {
   console.log(this.age);
}

let child1 = new Child("yhd".19);
child1.colors.push("pink");
console.log(child1.colors); // ["red", "blue", "yellow", "pink"]
child1.sayAge(); / / 19
child1.sayName(); // "yhd"

let child2 = new Child("wxb".30);
console.log(child2.colors);  // ["red", "blue", "yellow"]
child2.sayAge(); / / 30
child2.sayName(); // "wxb"

Copy the code

In the example above, the Parent constructor defines the name and colors attributes, and then adds a sayName() method to its prototype. The Parent constructor is called inside the Child constructor, passing in the name argument, and child.prototype is assigned to the Parent instance, then adding a sayAge() method to its prototype. This creates two instances of child1 and child2, each with its own attributes, including colors, and sharing the sayName method of the parent class

Advantages:

  1. Methods of the parent class can be reused
  2. You can pass parameters to the Parent constructor from the Child constructor
  3. Referenced properties in the parent constructor are not shared

Iv. Inheritance of the original type

A shallow copy of a parameter object

function objectCopy(obj) {
  function Fun() {}; Fun.prototype = obj;return new Fun()
}

let person = {
  name: "yhd".age: 18.friends: ["jack"."tom"."rose"].sayName:function() {
    console.log(this.name); }}let person1 = objectCopy(person);
person1.name = "wxb";
person1.friends.push("lily");
person1.sayName(); // wxb

let person2 = objectCopy(person);
person2.name = "gsr";
person2.friends.push("kobe");
person2.sayName(); // "gsr"

console.log(person.friends); // ["jack", "tom", "rose", "lily", "kobe"]
Copy the code

Advantages:

  1. Superclass methods are reusable

Disadvantages:

  1. References to the parent class are shared by all subclasses
  2. A subclass instance cannot pass arguments to its parent class

The object.create () method of ES5 has the same effect as the objectCopy() method here with only the first argument


Parasitic inheritance

Make a shallow copy of a target object using primitive inheritance to enhance the capability of the shallow copy

function objectCopy(obj) {
  function Fun() {}; Fun.prototype = obj;return new Fun();
}

function createAnother(original) {
  let clone = objectCopy(original);
  clone.getName = function () {
    console.log(this.name);
  };
  return clone;
}

let person = {
     name: "yhd".friends: ["rose"."tom"."jack"]}let person1 = createAnother(person);
person1.friends.push("lily");
console.log(person1.friends);
person1.getName(); // yhd

let person2 = createAnother(person);
console.log(person2.friends); // ["rose", "tom", "jack", "lily"]
Copy the code

Parasitic combination inheritance

function objectCopy(obj) { function Fun() { }; Fun.prototype = obj; return new Fun(); } function inheritPrototype(child, parent) { let prototype = objectCopy(parent.prototype); Prototype. Constructor = child; // Add object Child. Prototype = prototype; } function Parent(name) {this.name = name; this.friends = ["rose", "lily", "tom"] } Parent.prototype.sayName = function () { console.log(this.name); } function Child(name, age) { Parent.call(this, name); this.age = age; } inheritPrototype(Child, Parent); Child.prototype.sayAge = function () { console.log(this.age); } let child1 = new Child("yhd", 23); child1.sayAge(); // 23 child1.sayName(); // yhd child1.friends.push("jack"); console.log(child1.friends); // ["rose", "lily", "tom", "jack"] let child2 = new Child("yl", 22) child2.sayAge(); // 22 child2.sayName(); // yl console.log(child2.friends); // ["rose", "lily", "tom"]Copy the code

Advantages:

  1. The superclass constructor is called only once
  2. Child can pass parameters to Parent
  3. Superclass methods can be reused
  4. Reference properties of the parent class are not shared

Parasitic combinatorial inheritance is the best model for reference type inheritance