 
总览

一、借助构造函数
| 1 | function Parent1() { | 
缺点
子类没有继承父类的原型方法 只继承了父类构造函数中的属性和方法
| 1 | Parent1.prototype.method = (arg) =console.log(arg); | 
二、借助原型链
| 1 | function Parent2() { | 
原型图如下

缺点
引用类型的属性被所有实例共享,实例之间会互相影响
| 1 | let c21 = new Child2(); | 

三、组合(构造+原型链)
| 1 | function Parent3() { | 
优点
每个实例不会再互相影响
缺点
实例化时,父类被构造了两次,这没有必要 call一次,new一次
四、组合优化一
| 1 | function Parent4() { | 

缺点
无法判断实例的构造函数是父类还是子类
| 1 | let c41 = new Child4(); | 
但其实,构造函数就是父类本身
| 1 | console.log(c41.constructor); // Parent4 | 
很难得才通过Parent4.call(this)改变了构造函数的指向,现在又改回去了?天……不想看下去了行不行,兄dei,坚持一会就是胜利,别打瞌睡
Child4.prototype = Parent4.prototype只是把Child4的prototype属性指针指向了Parent4.prototype这个引用对象而已,实际上Parent4.prototype.constructor = Parent4

五、组合优化二
| 1 | function Parent5() { | 
但是,这时候,实例对象的constructor依然是Parent5

所以需要重新指定实例对象的构造器
| 1 | Child5.prototype.constructor = Child5; | 
| 1 | let c51 = new Child5(); | 
 
        