JS的继承

4 篇文章 0 订阅
1 篇文章 0 订阅

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

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();//小明
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 无法获取父类原型上的方法
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();//小明
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();//小明
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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值