接下来在总结 es6 的 class 之前,回顾总结一下 ES5 实现继承的方法
原型链
如果我们让一个实例的原型等于另一个实例,此实例的原型将包含一个指向另一个原型的指针。
举例子:
1 | function Animal(name = "动物") { |
这里定义了 Animal 和 Dog 两个类型,其中 Dog 通过把 prototype 赋值给 Animal 的实例从而继承了 Animal,这样 Dog 的新原型不仅有 Dog 的属性和方法,也有 Animal 中的属性和方法,因为 prototype 被改写,dog1 的 constructor 指向 Animal。
使用isPrototypeOf()
或者 instanceof
可以确定实例和构造函数之原型链间的关系
1 | console.log(Object.prototype.isPrototypeOf(dog1)); //true |
和上篇创建对象遇到的问题一样,包含引用类型之的原型属性会被所有实例共享
1 | function Animal(name = "动物") { |
很明显,我们不会想让柯基去吃哈士奇的狗粮,导致上述问题的原因是 dog dog1 实例的原型是同一个 Animal 的实例,自然是共用属性。
原型链还有第二个问题,就是创建 Dog 的时候没有办法向 Animal 传递参数。
构造函数
解决上面的问题可以用借用构造函数的技术
1 | function Animal(name = "动物") { |
看看就行,跟上一篇创建对象的构造函数方法一样,都是执行构造函数的代码。缺点也类似,没有解决函数重用的问题。最常使用的是组合继承。
组合继承
1 | function Animal(name = "动物") { |
实际上组合继承的属性是通过创造出子类的 this 后将父类的中的属性添加到 this 上。方法是通过重写子类的 prototype 后拿到父类实例及其原型的方法。
组合继承避免了原型链和借用构造函数的缺陷。是 Js 中最常用的继承。