Several types of inheritance in Javascript? How to achieve inheritance?

In JavaScript, inheritance is an important development idea in object-oriented development. The core is to allow object A to use the properties and methods of object B. To put it bluntly, it is for resource integration to make our code more reusable. Maintainability and scalability are also higher.

In JS, each object has its own prototype object. Inheritance in JS depends on this prototype object, and the prototype object also has its own prototype object. It is these prototype objects that form the prototype chain. This is the inheritance core.

for example :

There was an old father who worked hard for half his life and built a big house

At this time, no matter how many sons the old father has, his sons can all live in this house

All contents of this house can be used

But if there is no inheritance, then each of his sons will have to build a new house by themselves

This is the meaning of our inheritance. Next, we will talk about the common inheritance schemes in JavaScript in detail.

 Review previous knowledge points

prototype

The constructor (class) has its own attribute prototype, which is an object, and each object has its own attribute __proto__, which points to the prototype of the constructor to which it belongs. In this way, the constructor and the object are connected.

prototype chain

The prototype chain is the object chain structure that __proto__ is connected in series, and each object will have its own prototype object ( __proto__ ).

Prototype Chain Access Rules

The access rules of object members are accessed according to the mechanism of the prototype chain. When you access the members of an object, you will first search in the object itself.

If you have it, use your own directly. If you don’t have it, you will automatically go to your own __proto__ to find it. If you don’t have it, continue to find it in __proto__, and so on, until there is no Object.prototype, then return null.

 Back to common inheritance schemes

1. Prototype chain inheritance

● The essence is to do some tricks on the prototype chain, so that the __proto__ of a certain object can point to another object.

● Core: the prototype of the subclass points to the instance of the parent class

// 父类
function Person(name) {
  this.name = name
}
Person.prototype.sayHi = function () { 
  console.log('hello world') 
}

// 子类
function Student(age) {
  this.age = age
}

// 实现继承
Student.prototype = new Person('千锋大前端')

const s = new Student(10)
console.log(s)

Disadvantage: The subclass does not have its own prototype, because the prototype of the subclass is the instance of the parent class. In terms of inheritance properties, the properties inherited by all subclass instance objects are exactly the same.

Advantages: properties and methods can be inherited.

2. Borrow constructor inheritance

The essence is to use the parent class constructor as an ordinary function, and use some methods to change the point of this

Core: use call or apply method to call the parent class constructor, let its this point to the instance of the subclass

// 父类
function Person(name) {
  this.name = name
}
Person.prototype.sayHi = function () { 
  console.log('hello world') 
}

// 子类
function Student(age, name) {
  this.age = age

  // 实现继承
  Person.call(this, name)
}

const s = new Student(10, '千锋大前端')
console.log(s)

Disadvantages  : Only the properties of the parent class can be inherited, and the methods on the prototype cannot be inherited.

Advantages  : Subclasses have their own prototypes, and can add content specific to subclasses to their prototypes. For inherited properties, each instance of a subclass inherits a set of its own properties.

3. Basic Composition Inheritance

The essence is to combine the above prototypal inheritance and borrowed constructor inheritance, and combine the advantages of the above two inheritance methods together, known as the earliest perfect inheritance.

// 父类
function Person(name) {
  this.name = name
}
Person.prototype.sayHi = function () { 
  console.log('hello world') 
}

// 子类
function Student(age) {
  this.age = age
  
  // 实现继承( 目的 : 继承属性 )
  Person.call(this, name)

}

// 实现继承( 目的 : 继承方法, 属性不重要 )
Student.prototype = new Person()

const s = new Student(10, '千锋大前端')
console.log(s)

4. Parasitic inheritance

The essence is to use an empty object to wrap the instance object of the parent class, then set the prototype of the empty object as the prototype object of the parent class, and finally return the empty object as the instance object of the subclass, thereby realizing inheritance.

function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHi = function() {
  console.log('hello world')
}

function Student(parent, name) {
  let student = Object.create(parent)
  student.name = name
  student.sayHello = function() {
    console.log(`Hello, my name is ${this.name}`)
  }
  return student
}

let parent = new Parent('千锋大前端')
let student = createChild(parent, '千锋大前端')

student.sayHello()
student.sayHi()

5. Parasitic Composition Inheritance

This is a very classic inheritance scheme, which is created by combining parasitic inheritance and basic compositional inheritance. It also solves the embarrassment of repeatedly calling constructors in compositional inheritance, and also avoids prototypes in parasitic inheritance Chain pollution is a solution that I personally think is very good and can be inherited. I don’t know which master came up with the solution.

In parasitic composition inheritance, we first use composition inheritance to create the relationship between objects and prototypes, and then correct unnecessary properties on the prototype through parasitic inheritance

// 寄生继承实现函数
function inheritPrototype(student, person) {
  // 创建父类原型的一个副本
  let prototype = Object.create(person.prototype)
  // 修正副本的 constructor 属性
  prototype.constructor = student
  // 将修正后的原型赋值给子类
  student.prototype = prototype
}

// 父类
function Person(name) {
  this.name = name
}
Person.prototype.sayHi = function() {
  console.log('hello world')
}

// 子类
function Student(age, name) {
  this.age = age
  // 借用继承( 目的 : 继承属性 )
  Person.call(this, name)
}

// 寄生继承
inheritPrototype(Student, Person)

// 向子类自己的原型上添加方法
Student.prototype.sayHello = function() {
  console.log(`Hello, My name is ${ this.name }`);
}

let instance = new Student(10, '千锋大前端')
instance.sayHello()
instance.sayHi()

6. ES6 class inheritance syntax

In the ES6 specification, the syntax of class inheritance appeared, that is to say, we don’t need the above messy things, and we can directly use the extends keyword to inherit the parent class directly.

Note: You also need to write a super in the constructor of the class to inherit the properties of the parent class

// 父类
class Person {
  constructor(name) {
    this.name = name;
  }

  sayHi () {
    console.log('Hello world')
  }
}

// 子类, 直接使用 extends 关键字继承父类
class Student extends Person {
  constructor(name, age) {
    // 继承父类属性
    super(name)
    this.age = age
  }

  sayAge() {
    console.log(`Hello, My name is ${ this.name }`)
  }
}

let instance = new Student('千锋大前端', 10)
instance.sayHello()
instance.sayHi()

Guess you like

Origin blog.csdn.net/JACK_SUJAVA/article/details/129528323