原型链
function parent(){
this.name = 'asd'
}
function child(){
}
child.prototype = new parent()
const instance = new child()
alert(instance.name) //'asd'
复制代码
因为此模式会共享属性和方法,所以当一个实例修改属性和方法时会影响其他实例,而且子类型无法向超类型传递参数。综上,不推荐使用此模式。
借用构造函数
function parent(name){
this.name = name
}
function child() {
parent.call(this,'sda')
this.age = 25
}
const instance = new child()
alert(instance.name) //'sda'
alert(isntance.age) //25
复制代码
此模式解决了上一模式的存在的两个问题,但还是存在一个小问题,所以还是不推荐使用。下面是此模式的优缺点。
- 每一个child的实例都有name属性的副本,避免了属性修改的传染性。
- 子类型可以向超类型传递参数
- 函数无法复用
组合继承
function parent(name) {
this.name = name
this.colors = ['red']
}
parent.prototype.sayName = () => {
alert(this.name)
}
function child(name, age) {
parent.call(this, name)
this.age = age
}
child.prototype = new parent()
child.prototype.constructor = child
child.prototype.sayAge = () => {
alert(this.age)
}
复制代码
此模式完美的解决了前面两种模式存在的问题,适用于绝大多数的场景,因此推荐使用该模式。
原型式继承
const person = {
name: 'sa',
friends: ['ad', 'da']
}
function object(original) {
function F() {}
F.prototype = original
return new F()
}
//Object.create()是object()的规范实现
const anotherPerson = Object.create(person)
复制代码
该模式在一个对象的基础上创建一个类似的对象,优点是可以节省书写构造函数的代码。由于还是同原型式一样共享属性和方法,所以也具有原型式的问题。
寄生式继承
var person = {
name: 'sa',
friends: ['ad', 'da']
}
function createAnother(original) {
const clone = Object.create(original)
clone.say = () => {
alert('hello')
}
}
var anotherPerson = createAnother(person)
anotherPerson.say(); //hello
复制代码
该模式类似于原型式继承,不过这模式在内部实现了增强对象,而且此模式使用于任何返回新对象的函数,所以推荐使用。
寄生组合式继承
function inheritPrototype(child, parent) {
const portotype = Object.create(parent)
prototype.constructor = child
child.prototype = prototype
}
复制代码
由于该模式只调用了一次parent构造函数,因此避免了组合式调用两次parent构造函数所创建的不必要的、多余的属性。该模式可谓是结合了寄生式继承和组合式继承两种模式的优点,是上述模式的集大成者,所以该模式被广泛认为是引用类型最理想的继承范式。