原型鏈
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建構函式所建立的不必要的、多餘的屬性。該模式可謂是結合了寄生式繼承和組合式繼承兩種模式的優點,是上述模式的集大成者,所以該模式被廣泛認為是引用型別最理想的繼承正規化。