前几天去面试,被问到了js继承方面的问题,由于自己很久没去关注过这块了,导致回答得不尽人意!= =,因此本篇文章就准备重新梳理下这块的知识,废话不多说,开搞!
es5里的继承
在es6的class出现之前,都是通过一些hack的方式实现继承的,具体来说,主要有如下三种
- 原型链继承
- 构造函数继承
- 组合式继承
接下来就分别聊聊它们各自的实现
原型链继承
顾名思义,主要是通过 原型链 的方式来实现继承,核心关键点就是 将父类的实例赋值给子类的原型对象,下面给出代码示例
1 | function Parent(name) { |
这种方式的优点如下:
- 子类可以共享父类原型对象上的方法,节省内存
- 实现方式很简单
缺点如下:
- 由于父类的实例属性被共享,会存在子类实例同时修改父类实例属性的情况,从而导致冲突
构造函数继承
顾名思义,这种方式是借用 构造函数 来继承的,而不是依靠原型对象,下面给出代码示例
1 | function Parent(name) { |
这种方式优点如下:
- 由于子类实例 各自 拥有父类实例属性的一个副本,因此可以避免原型链继承中的冲突问题
- 实现方式简单
缺点如下:
- 由于父类实例属性和方法都各自生成一个副本存在于子类实例中,因此无法高效地进行 方法 复用,导致浪费内存空间
组合式继承
这种方式结合了上述两种方式的优点
- 利用原型链继承实现 方法的复用
- 利用构造函数继承实现 属性的独立副本
代码示例如下
1 | function Parent(name) { |
这种方式的唯一缺点就是 子类的原型对象上始终存在与其实例上一样的属性
es6里的继承
es6里的继承是官方推出的标准方式,主要利用 class 和 extends 关键字来实现,代码示例如下
1 | class Parent { |
在es6里的继承,需要注意的一点是 子类是没有自己的this,都是通过super来继承父类的this,然后在自己的constructor里修改继承过来的this
因此在子类的constructor里,super必须在使用到this的地方 之前 去调用,否则就会报错,super的本质就是 父类的constructor函数
结语
前端领域的知识浩如烟海,只有不断的学习与巩固才能真正领悟,学习力很重要,希望我和正在阅读本文的你都会拥有,好啦,over!