js six inheritance


There are six inheritance methods: constructor inheritance, prototype chain inheritance, combined inheritance, prototype inheritance, parasitic inheritance, and parasitic combined inheritance.

One, constructor inheritance

Use functions to implement inheritance

    //父类构造函数
    function Father(){
    
    
        this.name = "Father";
        this.say = function(){
    
    
            console.log(this.name);
        }
    }

    //子类构造函数
    function Son(){
    
    
        Father.call(this);  // 重点
    }

Important: Use call to introduce the parent class constructor into the subclass function (the parent class is copied in the subclass function)

test:

    let son1 = new Son();
    son1.say(); // Father

son1 successfully inherited the name attribute and say method of the parent class

But this is not inheritance in the traditional sense, because the objects generated by each Son subclass calling the parent class are independent of each other, that is, if the parent class wants to have a common attribute that is shared by all subclass instances, it is It can't be achieved.

advantage:

  1. Can inherit multiple constructors (multiple call is possible)
  2. All basic attributes are independent and will not be affected by other instances

Disadvantages:

  1. Cannot inherit the properties and methods of the parent class constructor (.prototype)
  2. Each new instance copies the parent constructor, if the parent class is very large, it will take up memory
  3. The reuse of public methods (function reuse) is not implemented, and a new function is created every time instead of sharing

2. Prototype chain inheritance

The most primitive way, through the prototype property inheritance

    //父级 构造函数
    function Father() {
    
    
        this.arr = [1,2,3];
    }

    //父级 原型属性
    Father.prototype.name = "tingting"
    
    //子级 构造函数
    function Son() {
    
    
    }

    //子级 原型属性: 继承父级
    Son.prototype = new Father() // 重点
    
    //创建子级的实例对象
    let son = new Son();

    console.log(son.name); // tingting

Important: The prototype of the subclass is equal to the instance of the parent class Son.prototype = new Father()

Explain how the son instance finds the name attribute.
If a certain attribute of an object cannot be found, it will look up along its prototype and stop searching until the end of the prototype chain.

  • First search in the son object itself, if not found
  • Find (Father()) in Son.prototype, if not found
  • On the upper level Son.prototype.__proto__(Father.prototype)
  • Until you find the required property or method, or reach the top of the prototype chain Object.prototype

But all the attributes and methods of the child instance are on the same instance of the parent class, so once a child instance modifies its method, all other child instances will be affected.
Look at the following code

    function Father() {
    
    
        this.arr = [1,2,3];
    }
    
    function Son() {
    
    
    }

    Son.prototype = new Father() 
    
    let son1 = new Son();
    let son2 = new Son();
    son1.arr.push(4);

    console.log(son1.arr); // 1,2,3,4
    console.log(son2.arr);// 1,2,3,4

After the child instance son1 modifies arr, the arr of the son2 instance is also modified

advantage:

  1. simple

Disadvantages:

  1. Cannot pass parameters to the parent class constructor
  2. All instances will share the properties of the parent instance (an instance is modified, then all properties will change)

Three, combination inheritance (prototype chain + constructor)

Combining prototype chain inheritance and borrowing constructor inheritance, integrating the advantages of the two, commonly used

    function Father(color) {
    
    
        this.color = color;
        
    }
    Father.prototype.print = function() {
    
    
        console.log(this.color);
    }
    function Son(color) {
    
    
        Father.call(this, color); // 借用构造函数继承
    }
    Son.prototype = new Father(); // 原型链继承let son1 = new Son('red');
    son1.print(); // redlet son2 = new Son('blue');
    son2.print(); // blue

In the Son subclass, Father.call is used to call the parent class constructor, and Son.prototype is assigned to the parent class instance
. After Father.call is used to call the parent class constructor, all subsequent new Son()instances created through Copy a copy of the properties and methods defined in the parent class constructor;
then assign the parent class instance to the subclass prototype prototype, all subclass instances can share the properties and methods on the parent class prototype;
therefore, define the parent class When writing , put private properties and methods in the constructor, and put shared properties and methods on the prototype

advantage:

  1. Can pass parameters
  2. Common functions can be reused
    Disadvantages:
  3. Called the parent class constructor twice, occupying memory

Four, prototype inheritance

The essence of prototypal inheritance is actually a shallow copy , using an object as a template to copy a new object

    // 封装一个函数容器,用来承载继承的原型
    function object(obj){
    
    
        function F(){
    
    }
        F.prototype = obj;
        return new F();
    }

    let father = {
    
    
        name: "father",
        arr: [1,2,3]
    }

    let son1 = object(father);

In the object function, define a constructor, use obj as a template, let the prototype object of the constructor point to obj, and then return an instance of the constructor, you can access all the properties and methods of the object obj.

Object.creat()

A new function Object.create() has been added to es5 to directly implement prototype inheritance. The
above code can be rewritten as:


    let father = {
    
    
        name: "father",
        arr: [1,2,3]
    }

    let son1 = Object.create(obj);

The essence is still prototype chain inheritance, which will also share the properties of the parent class

Five, parasitic inheritance

Parasitic inheritance is to encapsulate prototypal inheritance again, then extend new methods on the object, and then return the new object. It
can be understood as adding some functions or properties on the basis of prototypal inheritance

    function object(obj){
    
    
        function F(){
    
    }
        F.prototype = obj;
        return new F();
    }
    // 上面是原型式继承
    function create(obj){
    
    
        let clone = object(obj) // 或 Object.create(obj)

        clone.say = function(){
    
    
            console.log('123');
        }

        return clone;
    }
    // 用create函数封装了一遍,又增添了say方法
    let father = {
    
    
        name: "father",
        arr: [1,2,3]
    }

    let son = create(father);

    son.say(); // 123

Clone adds new methods to the object, and finally returns to clone, thus inheriting the object returned by object

advantage:

  1. No need to create custom types

Disadvantages:

  1. The prototype is not used and cannot be reused

6. Parasitic combined inheritance (commonly used)

The last inheritance method is the most perfect solution. It
is the realization principle of es6 class grammar. The main purpose is to solve the shortcomings of the need for new Father each time in combined inheritance, which leads to the execution of the parent class constructor.

    function Father(color) {
    
    
        this.color = color;
    }
    Father.prototype.print = function() {
    
    
        console.log(this.color);
    }
    function Son(color) {
    
    
        Father.call(this, color); 
    }

    Son.prototype = Object.create(Father.prototype); // 划重点let son1 = new Son('red');
    son1.print(); // redlet son2 = new Son('blue');
    son2.print(); // blue

This differs from a combination of inheritance and the only one, is the original Son.prototype = new Father();revised toSon.prototype = Object.create(Father.prototype);

The Object.createmethod mentioned in the prototype is to create a new object with the incoming object as the prototype; after the new object is created, it is assigned to Son.prototype, so Son’s prototype ultimately points to the prototype object of the parent class, which new Fatheris the same The effect of, and will not create redundant instances to occupy memory, but also can achieve multiple inheritance;

Guess you like

Origin blog.csdn.net/S_aitama/article/details/108757445