Javascript继承学习心得

时间:2022-01-07 14:14:50

在 Javascript 中,类的继承本质就是原型链。

以下是实现继承的几种方式:

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

原理:在子类初始化的时候,执行父类构造函数,并改变其this指向为子类,相当于将父类中的成员复制一份到子类中,这样子类也就有了和父类一样的成员

Demo:

Javascript继承学习心得

缺点:子类只能继承父类本身的成员,父类原型上的属性无法继承Javascript继承学习心得

 

2. 借助原型链实现继承

原理:让子类的原型指向父类的一个实例,这样子类实例不仅能访问父类本身的成员,父类原型上的属性也能访问

Demo:

Javascript继承学习心得

优点:解决了构造函数继承方式,子类实例无法访问父类原型上的属性的问题

Javascript继承学习心得

缺点:如果父类中有引用类型的数据,创建多个子类实例,修改其中一个子实例中的该引用类型数据,其他的子实例也会受影响

修改 Demo:

Javascript继承学习心得

Javascript继承学习心得

 

3. 组合继承

原理:结合构造函数继承和原型链继承

Demo:

Javascript继承学习心得

优点:

  1. 避免了构造函数继承时的子实例不能访问父类原型上的属性

  2. 避免了原型链继承时的修改一个子实例引用类型数据时,其他子实例该属性受影响的问题

缺点:父构造函数被执行了两次,子实例初始化的时候被调用一次,修改子类原型的时候被执行一次

修改:避免构造函数被执行两次,而是在只在初始化的时候被执行一次

Javascript继承学习心得

存在问题:和上面一样,其实都存在另一个问题,就是无法判别子实例到底是子类直接初始化的,还是父类初始化的

Javascript继承学习心得

原因:因为子类原型是父类的原型,所以,子类原型中的构造器其实是指向父类的,所以,子实例的 __proto__ 中的 constructor 指向父类

再修改:

Javascript继承学习心得

原理:

  1. Object.create() 方法,返回的是一个空对象,而这个空对象的原型就是传入的参数对象

  2. 给这个中间对象,也就是 Object.create 返回的空对象,丰富 constructor 属性,指向子类构造函数

  3. 把这个中间对象,作为子类的原型,它的 constructor 自然是指向子类的,并且因为它本身的原型是父类的原型,所以在整个原型链上,子类自然也能访问父类原型上的属性

Javascript继承学习心得

 

最终实现类型继承:

function F () {}

function Z () {
  F.call(this)
}
Z.prototype
= Object.create(F.prototype) Z.prototype.constructor = Z