組合繼承
原理:使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承欧宜,而通過(guò)借用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承坐榆。舉例:
// 父類
const Person = function(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayName = function() {
console.log(this.name)
}
// 子類
const Male = function(name, age) {
// 繼承屬性
Person.call(this, name, age)
this.gender = 'male'
}
// 繼承方法
Male.prototype = new Person()
// 把新的原型中的 constructor 指回自身
Male.prototype.constructor = Male
// test
const p1 = new Male('whh', 23)
console.log(p1)
// Male {name: "whh", age: 23, gender: "male"}
弊端:調(diào)用了兩次父類的構(gòu)造函數(shù),導(dǎo)致原型中產(chǎn)生了無(wú)效的屬性冗茸。
寄生組合式繼承
原理:通過(guò)借用構(gòu)造函數(shù)來(lái)繼承屬性席镀,通過(guò)原型鏈的混成形式來(lái)繼承方法匹中。主要就是用一個(gè)空的構(gòu)造函數(shù),來(lái)當(dāng)做橋梁豪诲,并且把其原型對(duì)象指向父構(gòu)造函數(shù)的原型對(duì)象顶捷,并且實(shí)例化一個(gè)temp,temp會(huì)沿著這個(gè)原型鏈跛溉,去找到父構(gòu)造函數(shù)的原型對(duì)象焊切。舉例:
// 父類
const Person = function(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayName = function() {
console.log(this.name)
}
// 子類
const Male = function(name, age) {
// 繼承屬性
Person.call(this, name, age)
this.gender = 'male'
}
// 寄生式組合繼承
const extend = function(subType, superType) {
const Temp = function() {}
// 把Temp構(gòu)造函數(shù)的原型對(duì)象指向superType的原型對(duì)象
Temp.prototype = superType.prototype
// 用構(gòu)造函數(shù)Temp實(shí)例化一個(gè)實(shí)例temp
let temp = new Temp()
// 把子構(gòu)造函數(shù)的原型對(duì)象指向temp
subType.prototype = temp
// 把temp的constructor指向subType
temp.constructor = subType
}
// 使用
extend(Male, Person)
// test
const p1 = new Male('whh', 23)
console.log(p1)
// Male {name: "whh", age: 23, gender: "male"}
這個(gè)例子的高效率體現(xiàn)在它只調(diào)用了一次 SuperType
構(gòu)造函數(shù)扮授,并且因此避免了在 SubType.prototype
上面創(chuàng)建不必要的芳室、多余的屬性。與此同時(shí)刹勃,原型鏈還能保持不變堪侯;因此,還能夠正常使用instanceof
和 isPrototypeOf()
荔仁。
目前程序猿認(rèn)為解決繼承問(wèn)題最好的方案
其他繼承方式(不完美的)
參考: 掘金地址
原型式繼承
// 原型式繼承
function createObjWithObj(obj){ // * 傳入一個(gè)原型對(duì)象
function Temp(){}
Temp.prototype = obj
let o = new Temp()
return o
}
// * 把Person的原型對(duì)象當(dāng)做temp的原型對(duì)象
let temp = createObjWithObj(Person.prototype)
// * 也可以使用Object.create實(shí)現(xiàn)
// * 把Person的原型對(duì)象當(dāng)做temp2的原型對(duì)象
let temp2 = Object.create(Person.prototype)
寄生式繼承
// 寄生式繼承
// 我們?cè)谠褪降幕A(chǔ)上伍宦,希望給這個(gè)對(duì)象新增一些屬性方法
// 那么我們?cè)谠褪降幕A(chǔ)上擴(kuò)展
function createNewObjWithObj(obj) {
let o = createObjWithObj(obj)
o.name = "whh"
o.age = 23
return o
}
拷貝繼承
const extend2(Child, Parent) {
let p = Parent.prototype
let c = Child.prototype
for (var i in p) {
c[i] = p[i]
}
}
這個(gè)函數(shù)的作用,就是將父對(duì)象的prototype對(duì)象中的屬性乏梁,一一拷貝給Child對(duì)象的prototype對(duì)象次洼。使用的時(shí)候,這樣寫:
extend2(Male, Person)
let p1 = new Male("whh", 23);
console.log(p1.age) // 23