JS 继承(委托更恰当)
引子: 上一篇文章中谈到了,原型的作用之一是实现继承。那么这篇文章会围绕继承来展开。 思路:继承一词真的恰当吗?何谓继承,何谓委托?有多少种方式实现继承?这些实现方式的演变如何去记忆?ES6 的 extends 关键字是用哪种继承方式实现的呢? JavaScript 是基于原型实现面向对象的,在 JS 中,面向对象概念中的继承是基于原型的。
常见的 JS 继承有 7 种方式:原型链继承和借用构造函数继承,二者结合诞生了组合继承;基于原型链继承和借用构造函数继承而衍生的 原型式继承和寄生式继承,二者结合诞生了最理想的寄生组合式继承。以及最后一种 ES6 的方式,class 语法糖。
0. 前言
定义
继承是类与类之间的关系。JS基于原型进行继承。
作用
使得子类具有父类的各种属性和方法。
1.原型链继承
function Parent() {}
function Child() {}
Child.prototype = new Parent()
优点:简单
缺点:1.属性被实例共享 2.不能向父类传递参数
2. 借用构造函数(经典继承)
function Parent(name) {}
function Child() {
Parent.call(this, name)
优点:1.避免了共享 2.可以向父类传参 缺点:方法在构造函数中定义,创建实例都会创建一遍方法.
3. 组合继承
function Parent() {}
function Child() {
Parent.call(this)
Child.prototype = new Parent()
Child.prototype.constructor = Child
优点:有 1、2 优点,最常用
缺点:调用了两次父亲构造函数
4. 原型式继承( 模拟 Object.create() )
function CreateObj(o) {
function F() {}
F.prototype = o
return new F()
优点:简单
缺点:属性被实例共享
5. 寄生式继承
function createObj(o) {
var clone = Object.create(o)
clone.sayName = function () {}
return clone
优点:简单 缺点:方法在构造函数中定义,创建实例都会创建一遍方法.
6.寄生组合式继承(最理想)
function Parent() {}
function Child() {
Parent.call(this)
var F = function () {}
F.prototype = Parent.prototype
Child.prototype = new F()
优点:1.高效率,只调用一次父构造函数 2.原型链不变
7. class ES6
ES6的class语法糖使用extends实现继承,其底层逻辑是利用寄生组合式继承。
利用网址 Traceur,Google公司出品 将ES6语法转为ES5,如下图所示:
上面图片中的ES6源码如下:
class Animal {
constructor(props, name) {
this.name = name
say() {
console.log('w