JS继承的几种方式

原型链继承

原型链继承-通过构造函数的实例对象继承

 <script>
        function GaoBW(){
            this.car = '兰博基尼';
            this.house = '温哥华山庄别墅1001号';
        }

        function Father(n,a){
            this.name = n;
            this.age = a;
        }

        Father.prototype = new GaoBW();

        var tc_  = new Father('铁锤',10); 
        console.log(tc_.name,tc_.car,tc_.house);//铁锤 兰博基尼 温哥华山庄别墅1001号
    </script>

这种继承方式的弊端是:当前函数的原型对象和实例对象的constructor指针会指向被继承函数

造成继承链紊乱

constructor属性默认指向当前构造函数,但是当进行 Father.prototype = new GaoBW();操作时;

当前函数的显性原型prototype属性(是一个对象)的constructor指针就指向 构造函数 GaoBW()

而实例对象通过_ _proto_ _属性(也叫隐式原型,也是一个对象)继承 Father.prototype的内容,所以他的constructor指针也指向构造函数 GaoBW();

 console.log(tc_.constructor); //结果是GaoBW,

解决方式:Father.prototype.constructor=Father;手动修改继承链。

原型链继承-通过构造函数prototype属性继承

<script>
        function GaoBW(){}
  
        GaoBW.prototype.house = '温哥华山庄别墅1001号';
        GaoBW.prototype.car = '兰博基尼';

        function Father(n,a){
            this.name = n;
            this.age = a;
        }

        Father.prototype = GaoBW.prototype;
        //手动修改继承链
        Father.prototype.constructor = Father;

        var tc_ = new Father('tc_',20);
        console.log(tc_.name,tc_.house,tc_.car);
        console.log(tc_.constructor);


    </script>

这种方式的

优点:效率比较高(不用执行和建GaoBw的实例了)

缺点:1、依然会产型继承链紊乱,需要修改继承链

2、因为father的原型对象指向了GaoBw的原型对象,所以father修改原型对象的值,高百万原型对象的值也被修改了,这样就等于继承了别人的财富,还要随意的更改别人的内容,太霸道,不合理


        Father.prototype = GaoBW.prototype;
        //手动修改继承链
        //Father.prototype.constructor = Father;

        var tc_ = new Father('tc_',20);
        console.log(tc_.name,tc_.house,tc_.car);
        console.log(tc_.constructor);

        // 另一个弊端
        Father.prototype.car = '五菱宏光';
        var gbw_ = new GaoBW();
        console.log(gbw_.car);//五菱宏光

因为GaoBW.prototype;属于引用数据类型当他赋值的时候不是直接传递的数据内容,而是在栈中的地址(用16进制表示),该地址指向堆中的内容。

 所以当 Father.prototype的内容修改时,GaoBW.prototype的内容也会发生变化;

引入空对象继承

为了解决当前原型影响被继承函数原型的问题,我们可以引入一个空的对象作为一个中转站

<script>
        function GaoBW(){}
        GaoBW.prototype.car = '兰博基尼';
        GaoBW.prototype.house = '温哥华山庄别墅1001号';

        function F(){}
        F.prototype= GaoBW.prototype;

        function Fater(n,a){
            this.a=a;
            this.n=n;
        }

        Fater.prototype = new F();
		Fater.prototype.constructor=Fater;

        var tc_ = new Fater('tc',20);
        console.log(tc_.car,tc_.house)//'兰博基尼','温哥华山庄别墅1001号'

        Fater.prototype.car = '五菱';
        var gao_ = new GaoBW();
        console.log(gao_.car);//兰博基尼
    </script>

构造函数继承

call方法&&apply方法

call:

语法:

a.call(b,ag1,ag2);

表示b继承a,ag1,ag2是a的参数

apply:

语法:

a.apply(b,[ag1,ag2]);

表示b继承a,ag1,ag2是a的参数


    <script>
        function Father(house,car){
            this.car_=car;
            this.house_ = house;
        }

        function Son(n,age){
            this.n_=n;
            this.age_ = age;
            //son 继承 father
            //a.call(b,ag1,ag2);
            //表示b继承a,ag1,ag2是a的参数
            Father.call(this,'汤臣一品','大众捷达');
            //Father.apply(this,['汤臣一品','大众捷达']);
        }
        var son_ = new Son('小宝',20);
        console.log(son_.house_);//汤臣一品
        console.log(son_.car_);//大众捷达

    </script>

call和apply继承主要通过传参的方式实现,两者的区别就是apply继承的参数是数组的形式

但是两者都无法访问被继承函数原型对象里的内容

  Father.prototype.hobby='sing'
 console.log(son_.hobby);//undefined

伪经典继承(组合继承)

将原型链继承和构造函数继承组合在一块

原型链实现对原型属性和方法的继承

借用构造函数实现对实例属性的继承

<script>
    function Father(house, car) {
        this.car_ = car;
        this.house_ = house;
    }

    Father.prototype.say = function(){
        console.log('我是祖宗');
    }

    function Son(n,a){
        this.name = n;
        this.age = a;
        // Father.call(this,'汤臣一品','劳斯莱斯');
        Father.apply(this,['汤臣一品','哈罗单车']);
    }

    Son.prototype = new Father();// 
    Son.prototype.constructor = Son;//手动更改原型对象

    var xw = new Son('小王',30);
    console.log(xw.car_,xw.house_,xw.name,xw.age);

    console.log(xw.constructor);// Son

    xw.say();// 我是祖宗
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值