Six ways of inheritance (js)

1. Simple prototype chain

        // 创建要继承的父类
        function Father() {
    
    
            // 自带的属性和方法
            this.name = "li";
            this.show = function() {
    
    
                console.log("帅");
            }
        };

        // 在父类的原型上添加方法
        Father.prototype.callback = function() {
    
    
            console.log(this.name);
        }

        // 定义Son
        function Son() {
    
    

        }

        // 令Son继承Father
        Son.prototype = new Father();// 这句是原型链继承的重点

        // 创建Son的对象实例
        var son = new Son();
        var son1 = new Son();

        console.log(son.name); // 可以调用继承于父类上的属性
        son.show(); //  可以调用继承于父类上的方法
        son1.callback(); // 可以调用father中原型上添加的方法

Focus :

Let the prototype of the new instance equal the instance of the parent class.

Advantages :

Simple and easy to implement

Disadvantages :

  1. The reference properties of the prototype object are shared by all instances .
        // 创建要继承的父类
        function Father() {
    
    
            // 自带的属性和方法
            this.name = "li";
        };

        // 定义Son
        function Son() {
    
    

        }

        // 令Son继承Father
        Son.prototype = new Father(); // 这句是原型链继承的重点

        // 创建Son的对象实例
        var son = new Son();
        var son1 = new Son();
        son1.__proto__.name = "zhang"; //通过一个实例改变Son的prototype上的name

        // 导致所有实例的name都改变,就叫做引用值共享
        console.log(son.name); //"zhang"
        console.log(son1.name); //"zhang"
  1. When creating a subclass instance, you cannot pass parameters to the parent class constructor
  1. Single inheritance

2. Constructor inheritance

        // 创建父类
        function Father(name) {
    
    
            this.name = name;
            this.arr = [1];
            this.show = function() {
    
    
                console.log("shuai");
            }
        }
        Father.prototype.call = function() {
    
    
            console.log("call");
        };
        // 创建子类
        function Son(name) {
    
    
            // 借父类的构造函数来增强子类实例,等于是把父类的实例属性复制了一份给子类实例装上了(完全没有用到原型)
            Father.call(this, name); // 核心代码
        }
        var son1 = new Son("n1");
        var son2 = new Son("n2");

        son1.arr.push(2); // 向son1的数组中添加一个数

        console.log(son1);
        console.log(son2);
        // 这时son实例的prototype的原型是object
        console.log(son1.show === son2.show); // false

Focus :

Use .call() and .apply() to introduce the parent class constructor into the subclass function (self-execution (copy) of the parent class function is done in the subclass function)

Advantages :

  1. Only inherit the properties of the parent class constructor, not the properties of the parent class prototype
  1. Solve the shortcomings of prototype chain inheritance
  1. Can inherit the attributes of multiple constructors (using call())
  1. In the child instance, parameters can be passed to the parent instance.

Disadvantages :

  1. Can only inherit the properties of the parent class constructor
  1. Unable to realize the reuse of the constructor (recall each time it is used)
  1. Each new instance has a copy of the parent class constructor, bloated

3. Combination inheritance (combined prototype chain inheritance and borrowed constructor inheritance) (commonly used)

        // 创建父类
        function Father(name) {
    
    
            this.name = name;
            this.arr = [1];
            this.show = function() {
    
    
                console.log("shuai");
            }
        }
        Father.prototype.call = function() {
    
    
            console.log("call");
        };

        function Son(name) {
    
    
            Father.call(this, name); // 借用构造函数继承
        };

        Son.prototype = new Father(); // 原型链继承

        var son1 = new Son('li');
        var son2 = new Son('zhang');
        console.log(son1);
        console.log(son2);

Focus :

Combines the advantages of the two modes, parameter transfer and multiplexing

Advantages :

  1. Can inherit the attributes on the parent class, can pass parameters, can be reused
  1. The constructor attributes introduced by each new instance are private .

Disadvantages :

The parent class constructor is called twice (memory consumption), and the subclass constructor will replace the parent class constructor on the prototype.

4. Prototype inheritance

        // 创建父类
        function Father(name) {
    
    
            this.name = name;
            this.arr = [1];
            this.show = function() {
    
    
                console.log("shuai");
            }
        }

        Father.prototype.call = function() {
    
    
            console.log("call");
        };
        // 生育函数
        function beget(obj) {
    
    
            function F() {
    
    }
            F.prototype = obj; //继承了传入的参数
            return new F(); //返回函数对象
        }

        var son1 = new Father(); // 先拿到父类的对象
        console.log(son1);

        // (核心代码)
        var son2 = beget(son1); // 将父类中的属性赋值到每一个子类的函数的原型中
        var son3 = beget(son1); // 同上  

        son2.name = "zhang"; // 修改实例中的属性

        console.log(son2);
        console.log(son3);
        console.log(son2.call); //子类的实例都可以访问父类的原型上的属性和方法

Focus :

Wrap an object with a function, and then return the call of this function. This function becomes an instance or object that can add properties at will. (Each time an object instance is created, a new function is returned),

Advantages :

Copy an object and wrap it with a function.

Disadvantages :

  1. All instances inherit the properties on the prototype.
  1. Unable to achieve reuse.

V. Parasitic inheritance

        // 创建父类
        function Father(name) {
    
    
            this.name = name;
            this.arr = [1];
            this.show = function() {
    
    
                console.log("shuai");
            }
        }

        Father.prototype.call = function() {
    
    
            console.log("call");
        };

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

        var son = new Father();



        // 将原型式继承的核心代码套一个壳子
        function getSubObject(obj) {
    
    
            var clone = beget(obj); // 核心
            return clone;
        }

        var son1 = getSubObject(new Father());
        console.log(son1);

Focus :

It puts a shell around prototype inheritance.
Advantages :

No custom type is created, because it just sets a shell to return the object (this one), this function naturally becomes a new object created.

Disadvantages :

The prototype is not used and cannot be reused.

6. Parasitic combined inheritance (commonly used)

Parasite :

Return the object in the function and then call

Combination :

1. The prototype of the function is equal to another instance.

2. Use apply or call to introduce another constructor in the function, which can pass parameters

        // 创建父类
        function Father(name) {
    
    
            this.name = name;
            this.arr = [1];
            this.show = function() {
    
    
                console.log("shuai");
            }
        }

        Father.prototype.call = function() {
    
    
            console.log("call");
        };

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

        var bet = beget(Father.prototype);
        // 继承了父类函数的原型
        
        function Son() {
    
    
            Father.call(this);
        }
        Son.prototype = bet; //继承了get的实例;

        bet.constructor = Son; // 修复实例
        var son1 = new Son();
        // Sub的实例就继承了构造函数的属性,父类实例,
        console.log(son1.call);

Key point : fixed the problem of combinatorial inheritance

Guess you like

Origin blog.csdn.net/weixin_45773503/article/details/108758825