[Notes] [Javascript] javascript implements inheritance

foreword

  • I wrote an article about object-oriented programming before , and learned about Javascript’s inheritance method by reading other people’s blogs, and used pictures to help understand. The pictures were made by myself. If there are any deviations, please help readers point out, thank you.
  • Some of the notes in the notes have been sorted out after personal understanding, and there may be deviations. Readers are also kindly requested to help point out, thank you.

disclaimer

  • For convenience, some of the pictures used in this article come from the Internet. If there is any infringement, please contact the blogger to delete it. Thanks to other bloggers for their pictures.
  • This note is used to record my summary of this knowledge. To facilitate future work and study.
  • If there is any infringement, please inform and delete it immediately.

How does javascript implement inheritance?

[What is inheritance?

  • The subclass has the characteristics and behavior of the parent class

    • feature == attribute
    • behavior == method

【How to do it?

//父类
function Person(name){
    
    //给构造函数添加了参数
    this.name = name;
    this.msg = function(){
    
    
        alert(this.name);
    }
}
Person.prototype.age = 10;//给构造函数添加了原型属性

Method 1: Prototype Chain Inheritance

Step 1: Create a subclass, and point the prototype object of the subclass to the instance of the parent class** (key point)**

//创建子类
function Sub(){
    
    
    this.name = 'roy';
}
//子类的原型对象指向父类实例
Sub.prototype = new Person();

Step 2: Create a subclass instance, at this time the subclass instance has completed inheritance

var sub1 = new Sub();

Step 3: Verify whether the inheritance is successful (in fact, only the above two steps are enough to realize the inheritance, this step belongs to calling the parent class, and checking whether the inheritance is successful)

console.log(sub1.age);//10
//instanceof 判断元素是否在另一个元素的原型链上
//sub1继承了Person的属性,返回true
console.log(sub1 instanceof Person);//true

【analyze】

  • advantage
    • Implemented inheritance
      • √ Attributes of the constructor of the instance (that is, the attributes of the constructor of the subclass)
      • √ Attributes of the constructor of the parent class
      • √ Attributes of parent class prototype
  • shortcoming
    • The new instance cannot pass parameters to the parent class constructor
      • [Reason] In step 2, a new instance is created through the subclass instead of the parent class
    • single inheritance
      • [Reason] As shown in Figure (1), a subclass only inherits one parent class
    • Modifying the properties of the subclass instance will change the properties of the parent class.
      • 【Reason】As shown in Figure (1)

Method 2: Constructor inheritance

Step 1: Call back the parent class constructor in the subclass constructor (key point)

function Sub(){
    
    
    Person.call(this,'roy');
    this.age = 12;
}

Step 2: Create subclass instance

var sub1 = new Sub();

Step 3: Check whether the inheritance is successful

console.log(sub1.name);//roy
console.log(sub1.age);//12
console.log(sub1 instanceof Person);//false

【analyze】

  • advantage
    • Implemented inheritance:
      • √ Inherit the attributes of the parent class constructor
      • ✕ Inherit the properties on the prototype of the parent class (as shown in Figure (3))
    • You can pass parameters to the parent class constructor
  • shortcoming
    • Unable to achieve reuse of parent class constructor
      • [Reason] Use it once, call the parent class constructor again
    • Each new instance has a copy of the parent constructor, bloated
      • [Reason] A closure is generated in the subclass constructor, and the closure causes a memory leak
    • Cannot inherit properties on the prototype of the parent class
      • 【Reason】As shown in Figure (3)

Method Three: Combined Inheritance

Step 1: Call back the parent class constructor in the subclass constructor **(key point)**

function Sub(name){
    
    
    Person.call(this,name);//构造函数继承
}

Step 2: Create a subclass, and point the prototype object of the subclass to the instance of the parent class **(key point)**

Sub.prototype = new Person();//原型链继承

Step 3: Create a subclass instance and check whether the inheritance is successful

var sub = new Sub('roy');
console.log(sub.name);//roy 继承了构造函数属性
console.log(sub.age);//10 继承了父类原型的属性

【analyze】

  • advantage:
    • Implemented inheritance:
      • √ Inherit the properties on the prototype of the parent class
    • You can pass parameters and reuse
    • Constructor properties introduced by each new instance are private
      • [Reason] Step 1 generated a closure
  • shortcoming:
    • The parent class constructor is called twice, consuming memory
    • The subclass constructor will replace the parent class constructor on the prototype (if you don’t understand, welcome friends to discuss in the comment area)

Method 4: ES6 Class class inheritance

In order to uniformly use the ES6 format parent class, also make changes (you can use the previous parent class directly without modification)

//父类
class Person {
    
    //给构造函数添加
  constructor(name) {
    
    
    this.name = name;
  }
  msg() {
    
    
    alert(this.name);
  }
}
Person.prototype.age = 10;//给构造函数添加了原型属性

Step 1: Use keywords extendsto inherit parent class methods and properties, keywords superinherit parent class constructor properties (key points)

class Sub extends Person {
    
      //继承父类方法
  constructor(name) {
    
    
    super(name);        //继承父类构造函数属性
    this.sex = 'boy';
  }
}

Step 2: Create a subclass instance and check whether the inheritance is successful

const sub = new Sub('lao');
console.log(sub.age);    	//10	//证明继承父类构造函数原型属性
console.log(sub.name);   	//lao
console.log(sub.sex); 		//boy
console.log(sub.msg());
console.log(sub instanceof Person);   //true

【analyze】

  • advantage:

    • implement inheritance
      • √ Inherit the properties on the prototype of the parent class
      • √ Inherit the attributes of the parent class constructor
    • written more concisely
  • shortcoming:

    • Function declarations cannot be automatically promoted (must be declared before use)

      【Example】

      let sub1 = new Sub()	//报错ReferenceError
      class Sub{
              
              }
      

Method 5: Prototype Inheritance

Step 1: Simulate the subclass constructor through a function (key point)

function content(obj){
    
    
    function F(){
    
    };			//模拟子类的构造函数
    F.prototype = obj;	//将子类构造函数原型对象设为父类实例
    return new F();			//创建子类构造函数实例
}

Step 2: Create an instance of the parent class

var person = new Person();

Step 3: Call the mock subclass constructor to simulate creating a subclass instance

var sub1 = content(person);

Step 4: Check whether the inheritance is successful

console.log(sub1.age);//10 继承了父类函数的属性

【analyze】

  • advantage:
    • Instead of defining subclasses, use an existing class to directly inherit from.
  • shortcoming:
    • All instances will inherit the properties on the prototype of the parent class (as shown in Figure (4))
    • Unable to achieve reuse (new instance attributes are added later)

PS: The principle of Object.create() is realized through prototype inheritance

[Abbreviation] The above-mentioned prototype inheritance can be abbreviated as follows

var person = new Person();
var sub1 = Object.create(person);
console.log(sub1.age);//10 继承了父类函数的属性

Method Six: Parasitic Inheritance

Step 1: Simulate the subclass constructor through a function (key point)

function content(obj){
    
    
    function F(){
    
    };
    F.prototype = obj;//继承了传入的参数
    return new F();//返回函数对象
}

Step 2: Create an instance of the parent class

var person = new Person();

Step 3: Create a function that is only used to encapsulate the inheritance process, and the interior of the function inherits the parent class in a certain way

function subObject(obj){
    
    
    var sub = content(obj);//通过调用函数
    sub.name = 'roy';//以某种方式来增强这个对象
  	sub.sayHi=function(){
    
    
      console.log('hello');
    }
    return sub;//返回子类
}

Step 4: Call a function to simulate creating a subclass instance

var sub1 = subObject(person);

Step 5:

console.log(typeof subObject);//function
console.log(typeof sub1);//object
console.log(sub1.name);//'roy' 返回了个sub对象,继承了sub的属性
sub1.sayHi();	//'hello'

【analyze】

  • advantage:
    • add function to object
  • shortcoming:
    • low efficiency
      • [Reason] Function reuse cannot be achieved

Method 7: Parasitic Composition Inheritance

Step 1: Create a new parent class and add methods to the parent class

function Parent6() {
    
    
  this.name = 'parent6';
  this.play = [1, 2, 3];
}
Parent6.prototype.getName = function () {
    
    
  return this.name;
}

Step 2: Create a subclass, and the callback inherits the properties of the parent class (key points)

function Child6() {
    
    
  Parent6.call(this);	//继承服父类的属性
  this.friends = 'child6';
}

Step 3: With the help of functions, parent-child class association (key point)

function clone(parent, child) {
    
    
  // 这里改用 Object.create 就可以减少组合继承中多进行一次构造的过程
  child.prototype = Object.create(parent.prototype);
  child.prototype.constructor = child;
}

clone(Parent6, Child6);

PS: The subclass constructor is equal to the parent class object

【prove】

console.log(child.prototype.constructor == parent); //true

Step 4: Add methods to subclasses

Child6.prototype.getFriends = function () {
    
    
  return this.friends;
}

Step 5: Verify Inheritance

let person6 = new Child6();
console.log(person6);	//输出:带有父类属性的对象>>>>>>证明:实现子类继承父类属性
console.log(person6.getName());	//输出:parent6>>>>证明:实现子类继承父类的方法
console.log(person6.getFriends());//输出:child6>>>证明:子类可以追加方法

Literature reference

[1] Greedy Cat, "JS Inheritance", Rare Earth Nuggets, 2021-04-29

[2] Little Operator, "JS Inheritance", Rare Earth Nuggets, 2020-06-13

Guess you like

Origin blog.csdn.net/weixin_45944495/article/details/130959368