javascript 面向对象 已经 继承的几种方式
类型的声明方式
es5
es6
实例化
类的继承
1.通过构造函数继承
基本原理 是通过改变Father函数this指向 来实现继承
这种继承方式的缺点就是不能继承借用构造函数的原型
例如 我们给Father的原型上添加一个say方法
我们可以看到 报错了 从原型上的也找不到say方法
2.通过原型链实现继承
我们执行 child.say()可以看到
说明这种方式可以解决通过构造函数的弊端 那么这种继承方式是否完美了呢
我们给father添加一个 home 属性
当我们在实例上 更改home属性的时候 我们发现 另一个实例的home属性也被更改了
这是为什么呢 因为实例对象 引用的home属性就是都是同一个对象(Father的实例) 当更改属性时 因为其他实例的引用的是同一个对象 所以一个实例改变父对象的属性的时候改变其他实例也跟着改变 那么该怎么解决这个问题呢 (我们可以发现只有改变父对象的属性时 才会影响到其他实例 我们可不可以结合 构造函数的优点和原型链的优点?)
3.组合模型继承
可以看到 改变实例的home其他实例的home不跟着改变
那么这种方式是否完美了呢 ?我们打印两个实例看看
组合模式优化1
结果
这个方式还有不足吗?其实还有的
当我们想知道某个实例是 那个构造函数的直接实例的时候 我们知道都知道用instanceof
我们发现 两个都是 true 因为instanceof 是基于构造函数还判断是否是它的实例
判断是否是一个类的实例还可以用constructor来判断
我们打印一下 child 构造函数
发现是Father 因为constructor在实例的原型对象上 因为我们上面设置 Child.prototype = Father.prototype 所以 chid引用的构造函数是 Father的构造函数
那么 我们给Child一个构造函数 不就可以解决上述的问题了么?但是 我们不能直接在Child.prototype上直接给constructor因为 Child.prototype 和 Father.prototype 引用的是同一个对象 ,那么我们能不能找一个对象 这个对象有Father的prototype 并且 这个对象的属性时空的
5.组合模型优化二
或者
打印 child.constructor
6.圣杯模型(跟5的原理是一样的)
总结
1.构造函数继承 实例有自己的属性 但是不能继承借用构造函数的原型
2.原型链继承 能继承借用构造函数的原型但是实例自己不能拥有自己的属性(能取到是因为去原型链上寻找)
3.组合模型(位优化) 能够结合1和2的优点互相弥补缺点 但是每次要多走一次构造函数
4.组合模型(优化一) 去除了多走构造函数的弊端 但是不能准确判断 是哪个类的实例
5.组合模式(优化二) 通过实例的构造函数 可以识别是哪个类的实例(用 instanceof 不能判断 因为实例会找原型链的构造函数)