浅谈JavaScript继承

前言

关于JavaScript继承相关的定义和方法网上已经有很多解释啦,本菜鸟就不抄抄写写惹人嫌了,本文主要探讨三种基本的继承方式并且给出优化方案。

正文

  1. 借助构造函数实现继承

    function Parent1() {

          this.name = '喵喵喵';
          this.arr = [1];
      }
       Parent1.prototype.say = function () {
           alert('我肯定没被继承,所以弹不出来');
       };
      function Child1() {
          Parent1.call(this); // 这里是借助构造函数实现继承的关键
      }
        var t1 = new Child1();
    

好的,我们来通过控制台看看结果:

图片描述

可以发现,Child1已经成功继承了Parent1构造函数中个属性,那么问题来了,Parent1原型的属性Child1继承了吗?

图片描述

答案是并没有!这就是借助构造函数实现继承的缺点,被继承对象原型上的属性不能被继承。

2.借助原型链实现继承

Tips:所有实例对象共享的属性和方法都放在prototype中

 function Parent2() {
    this.arr = [1];
    this.a = '1';
}
Parent2.prototype.say = function () {
    alert('终于被继承了');
};
function Child2() {
    this.type = '汪汪汪';
}
Child2.prototype = new Parent2(); // 这里是借助原型链实现继承的关键
var s1 = new Child2();
var s2 = new Child2();

我们再次打开控制台看看:

图片描述

ok!到这里,我们已经成功实现让Parent2中的属性以及它原型链上的属性都被继承。但是这里要注意包含引用类型属性的原型会被所有的实例共享。啥意思呢?Child2.prototype = new Parent2(); 这行代码把Parent2的实例赋给了Child2的原型,而Parent2中存在引用类型this.arr
图片描述

s1和s2本是Child2的两个不同实例,但修改s2.arr同样映射到s1.arr这个问题体现出了借助原型链实现继承的缺点: Parent2中的引用属性被Child2的实例共享了

3.组合方式实现继承(原型链 + 构造函数)

function Parent3() {
    this.type = '喵喵喵';
    this.arr = [1]
}
function Child3() {
    this.type = '汪汪汪';
    Parent3.call(this); // 与2的唯一区别是多了这一句
}
Child3.prototype =  new Parent3();
var s3 = new Child3();
var s4 = new Child3();

组合方式实现了Child3对Parent3构造函数内和原型上所有属性和方法的继承,并且Child3的实例对象之间也不会相互干扰。当然啦,厉害的看官已经发现了组合方式的问题:Parent3.call(this)、new Parent3();
在实现组合继承的过程中Parent3执行了两次,这其实是没有必要的。

  • 组合方式实现继承-优化
function Parent4() {
        this.type = '喵喵喵';
        this.arr = [1]
    }
    Parent4.prototype.cide = [1,2,3];
    function Child4() {
        this.type = '汪汪汪';
        Parent4.call(this);
    }
    Child4.prototype =  Parent4.prototype;// 优化重点
    var s5 = new Child4();
    var s6 = new Child4();

这种组合方式的优化方案其实可以分两步来看:
1) Parent4.call(this) 实现对构造函数中的属性和方法的继承
2)Child4.prototype = Parent4.prototype; 实现对构造函数的原型的属性和方法的继承

观察3中的代码我们可以发现,通过Parent3.call(this)我们规避了Parent构造函数中引用属性对child实例的影响,但如果Parent的原型中存在引用类型(Parent4.prototype.cide),那么在child的实例中修改该属性,同样会映射到其它实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值