javascript 面向对象 已经 继承的几种方式

类型的声明方式

es5

javascript 面向对象 已经 继承的几种方式

es6

javascript 面向对象 已经 继承的几种方式

实例化

javascript 面向对象 已经 继承的几种方式javascript 面向对象 已经 继承的几种方式

类的继承

1.通过构造函数继承

javascript 面向对象 已经 继承的几种方式javascript 面向对象 已经 继承的几种方式

基本原理 是通过改变Father函数this指向 来实现继承

这种继承方式的缺点就是不能继承借用构造函数的原型

例如 我们给Father的原型上添加一个say方法 

javascript 面向对象 已经 继承的几种方式

javascript 面向对象 已经 继承的几种方式

我们可以看到 报错了 从原型上的也找不到say方法

javascript 面向对象 已经 继承的几种方式

2.通过原型链实现继承

javascript 面向对象 已经 继承的几种方式

我们执行 child.say()可以看到

javascript 面向对象 已经 继承的几种方式

说明这种方式可以解决通过构造函数的弊端 那么这种继承方式是否完美了呢

我们给father添加一个 home 属性

javascript 面向对象 已经 继承的几种方式

当我们在实例上 更改home属性的时候 我们发现 另一个实例的home属性也被更改了

javascript 面向对象 已经 继承的几种方式

这是为什么呢 因为实例对象 引用的home属性就是都是同一个对象(Father的实例) 当更改属性时 因为其他实例的引用的是同一个对象 所以一个实例改变父对象的属性的时候改变其他实例也跟着改变  那么该怎么解决这个问题呢 (我们可以发现只有改变父对象的属性时 才会影响到其他实例  我们可不可以结合 构造函数的优点和原型链的优点?)

3.组合模型继承

javascript 面向对象 已经 继承的几种方式

javascript 面向对象 已经 继承的几种方式

可以看到 改变实例的home其他实例的home不跟着改变

那么这种方式是否完美了呢 ?我们打印两个实例看看

javascript 面向对象 已经 继承的几种方式

组合模式优化1 

javascript 面向对象 已经 继承的几种方式

结果

javascript 面向对象 已经 继承的几种方式

这个方式还有不足吗?其实还有的

当我们想知道某个实例是 那个构造函数的直接实例的时候 我们知道都知道用instanceof

javascript 面向对象 已经 继承的几种方式

我们发现 两个都是 true 因为instanceof 是基于构造函数还判断是否是它的实例 

判断是否是一个类的实例还可以用constructor来判断

我们打印一下 child 构造函数

javascript 面向对象 已经 继承的几种方式

发现是Father 因为constructor在实例的原型对象上  因为我们上面设置 Child.prototype = Father.prototype 所以 chid引用的构造函数是 Father的构造函数

那么 我们给Child一个构造函数 不就可以解决上述的问题了么?但是 我们不能直接在Child.prototype上直接给constructor因为 Child.prototype 和 Father.prototype 引用的是同一个对象 ,那么我们能不能找一个对象 这个对象有Father的prototype 并且 这个对象的属性时空的 

5.组合模型优化二

javascript 面向对象 已经 继承的几种方式

或者

javascript 面向对象 已经 继承的几种方式

打印 child.constructor

javascript 面向对象 已经 继承的几种方式

6.圣杯模型(跟5的原理是一样的)

javascript 面向对象 已经 继承的几种方式

总结

1.构造函数继承 实例有自己的属性 但是不能继承借用构造函数的原型

2.原型链继承 能继承借用构造函数的原型但是实例自己不能拥有自己的属性(能取到是因为去原型链上寻找)

3.组合模型(位优化) 能够结合1和2的优点互相弥补缺点 但是每次要多走一次构造函数

4.组合模型(优化一) 去除了多走构造函数的弊端 但是不能准确判断 是哪个类的实例

5.组合模式(优化二) 通过实例的构造函数 可以识别是哪个类的实例(用 instanceof 不能判断 因为实例会找原型链的构造函数)