• JS的继承


    继承:子类继承父类中的属性和方法(目的是让子类的实例能够调用父类的属性和方法)

    1.原型链继承

    原型链继承:让父类中的属性和方法在子类实例的原型链上(把父类的原型放到子类实例的原型链上,实例使用父类的属性和方法,是基于__proto__原型链查找机制完成的)

    子类.prototype = new 父类();
    子类.prototype.constructor = 子类; 子类的原型指向父类的实例,需要添加constructor属性,保证原型重定向后的完整性。

    优点:

    1. 父类方法和属性可以复用。

    缺点:

    1. 父类所有的引用数据类型会被多个子类共享(更改一个子类的数据。其他数据也会受影响)。
    2. 子类实例不能给父类构造函数传参。
           function Person(){
                this.name = '小明';
                this.eats = ['banner'];
                this.getName = function(){
                    console.log(this.name);
                }
            }
    
            Person.prototype.getA = function () {
                console.log(this.name);
            }
    
            function Child(){};
    
            Child.prototype = new Person();
            Child.prototype.constructor = Child; //原型重定向,需要添加constructor属性,保证原型的完整性
    
            const b1 = new Child();
            const b2 = new Child();
            b1.name = '小花';
            b1.eats.push('apple');
            console.log(b1.name); //小花
            console.log(b1.eats); //['banner', 'apple']
            b1.getName();//小花
            b1.getA();//小花
    
            console.log(b2.name);//小明
            console.log(b2.eats);//['banner', 'apple']
            b2.getName();//小明
            b2.getA();//小明
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    2.构造函数继承

    构造函数继承:使用call或者apply方法,将父类的构造函数绑定在子类上,即在子类构造函数中添加:
    父类.apply(this, arguments); 或 父类.call(this, arguments);

    优点:

    1. 引用类型数据不会被子类共享,更改一个也不会影响别的实例。

    缺点:

    1. 子类不能访问父类原型属性(Person.prototype)上的方法和属性。
    		function Person() {
                this.name = '小明';
                this.eats = ['banner'];
                this.getDo = function () {
                    console.log(this.name + '吃了' + this.eats);
                }
            }
    
            Person.prototype.getName = function () {
                console.log(this.name);
            }
    
            function Child() {
                Person.call(this, arguments);
            }
    
            const c1 = new Child();
            c1.name = '小三';
            c1.eats.push('apple');
            console.log(c1.name);//小三
            console.log(c1.eats);//['banner', 'apple']
            c1.getDo();//小三吃了banner,apple
            c1.getName();//Uncaught TypeError: c1.getName is not a function 无法获取父类原型上的方法
    
            const c2 = new Child();
            console.log(c2.name);//小明
            console.log(c2.eats);//['banner']
            c2.getDo();//小明吃了banner
            c2.getName();//Uncaught TypeError: c2.getName is not a function 无法获取父类原型上的方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    3.组合继承

    组合继承:就是原型链继承+构造函数继承

    优点:

    1. 父类的属性和方法都可以实现公用
    2. 父类的引用属性不会被被共享

    缺点:

    1. 会调用两次父类的构造函数,会有两份一样的属性和方法,影响性能。
            function Person() {
                this.name = '小明';
                this.eats = ['banner'];
                this.getDo = function () {
                    console.log(this.name + '吃了' + this.eats);
                }
            }
    
            Person.prototype.getName = function () {
                console.log(this.name);
            }
    
            function Child() {
                Person.call(this, arguments);
            }
            Child.prototype = new Person();
    		Child.prototype.constructor = Child;
    		
            const c1 = new Child();
            c1.name = '小三';
            c1.eats.push('apple');
            console.log(c1.name);//小三
            console.log(c1.eats);//['banner', 'apple']
            c1.getDo();//小三吃了banner,apple
            c1.getName();//小三
    
            const c2 = new Child();
            console.log(c2.name);//小明
            console.log(c2.eats);//['banner']
            c2.getDo();//小明吃了banner
            c2.getName();//小明
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    4.寄生组合继承

    寄生组合继承:利用一个干净的实例对象,来作为子类的原型,并且这个干净的实例对象还得继承父类的属性,然后结合组合继承。

    优点:完美解决其他继承方式存在的弊端问题。

    		function Person() {
                this.name = '小明';
                this.eats = ['banner'];
                this.getDo = function () {
                    console.log(this.name + '吃了' + this.eats);
                }
            }
    
            Person.prototype.getName = function () {
                console.log(this.name);
            }
    
            function Child() {
                Person.call(this, arguments);
            }
            
            Child.prototype = Object.create(Person.prototype);
            Child.prototype.constructor = Child;
    
            const c1 = new Child();
            c1.name = '小三';
            c1.eats.push('apple');
            console.log(c1.name);//小三
            console.log(c1.eats);//['banner', 'apple']
            c1.getDo();//小三吃了banner,apple
            c1.getName();//小三
    
            const c2 = new Child();
            console.log(c2.name);//小明
            console.log(c2.eats);//['banner']
            c2.getDo();//小明吃了banner
            c2.getName();//小明
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    5.ES6 class继承

    Class 可以通过extends关键字实现继承,让子类继承父类除私有属性外的属性和方法。

            class Person{
                constructor(){
                    this.name = '小明';
                    this.eats = ["苹果"];
                    this.getName = function (){
                        console.log(this.name);
                    }
                }
    
                get = () =>{
                    console.log('Person.prototype上的方法');
                }
            }
            class Child extends Person{}
            const c1 = new Child();
            c1.name = '小三';
            c1.eats.push('香蕉');
            console.log(c1.name);//小三
            console.log(c1.eats);//['苹果', '香蕉']
            c1.getName();//小三
            c1.get();//Person.prototype上的方法
    
            const c2 = new Child();
            console.log(c2.name);//小明
            console.log(c2.eats);//['苹果']
            c2.getName();//小明
            c2.get();//Person.prototype上的方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    参考链接

    参考链接

  • 相关阅读:
    面试算法27:回文链表
    C#FreeSql分库分表
    广和通入驻中国联通5G物联网OpenLab开放实验室,携手共赴5G扬帆新征程
    学习Source Generators之从swagger中生成类
    通付盾Web3专题 | 智能账户:数字时代基础单元
    PTA天梯赛训练 7-8 查验身份证 (15分)
    Ajax:万字总结精读笔记,学懂Ajax看这一篇就够了
    EtherCAT转EtherNET/IP协议网关控制EtherCAT伺服驱动器的方法
    Springboot旅游度假村管理系统34q0n计算机毕业设计-课程设计-期末作业-毕设程序代做
    如何介绍自己的项目经验?
  • 原文地址:https://blog.csdn.net/weixin_44716659/article/details/126365970