繼承的概念
繼承:子類可以訪問(wèn)父類的所有屬性和方法黎棠,并且可以對(duì)這些屬性和方法進(jìn)行擴(kuò)展
繼承的幾種方式
-
原型鏈繼承
利用原型讓一個(gè)對(duì)象繼承另一個(gè)對(duì)象的屬性和方法,轩性,即把一個(gè)對(duì)象的原型作為另一個(gè)對(duì)象的實(shí)例倘潜,這樣就可以繼承另一個(gè)對(duì)象的屬性和方法
優(yōu)點(diǎn):
- 簡(jiǎn)單易于實(shí)現(xiàn),父類的新增的實(shí)例與屬性子類都能訪問(wèn)
缺點(diǎn):
- 子類更改從父類繼承過(guò)來(lái)的引用類型的屬性淆珊,由于原型屬性中的引用類型屬性會(huì)被所有實(shí)例共享,因此會(huì)影響其他實(shí)例
- 創(chuàng)建子類實(shí)例時(shí)奸汇,沒(méi)有辦法在不影響其他實(shí)例的情況下向超類型的構(gòu)造函數(shù)中傳參施符、
- 可以在子類中增加實(shí)例屬性,如果要新增加原型屬性和方法需要在new 父類構(gòu)造函數(shù)的后面
- 無(wú)法實(shí)現(xiàn)多繼承擂找、
- 創(chuàng)建子類實(shí)例時(shí)戳吝,不能向父類構(gòu)造函數(shù)中傳參數(shù)
function People (name){ this.name = name this.say = function(){ console.log('hello') } } // 01.原型鏈繼承 function Child1 (age) { this.age = age } Child1.prototype = new People('xiaoming') let xiaoming = new Child1(18) console.log(xiaoming.name,xiaoming.age) // xiaoming 18
-
借用構(gòu)造函數(shù)
在函數(shù)內(nèi)部通過(guò)call或apply去繼承超類型屬性或方法
優(yōu)點(diǎn):
- 解決了子類構(gòu)造函數(shù)向父類構(gòu)造函數(shù)中傳遞參數(shù)
- 可以實(shí)現(xiàn)多繼承(call或者apply多個(gè)父類)
缺點(diǎn):
- 方法都在構(gòu)造函數(shù)中定義,無(wú)法復(fù)用
- 不能繼承原型屬性/方法贯涎,只能繼承父類的實(shí)例屬性和方法
function People (name){ this.name = name this.say = function(){ console.log('hello') } } function Child2 (name,age) { People.call(this,name) this.age = age } let xiaoming = new Child2('xiaoming',18) console.log(xiaoming.name,xiaoming.age) // xiaoming 18
-
組合繼承
使用原型鏈實(shí)現(xiàn)原型屬性和方法的繼承听哭,使用借用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承
優(yōu)點(diǎn):
- 函數(shù)可以復(fù)用
- 不存在引用屬性問(wèn)題
- 可以繼承屬性和方法,并且可以繼承原型的屬性和方法
缺點(diǎn): 需要調(diào)用兩次父類
function People (name){ this.name = name this.say = function(){ console.log('hello') } } function Child3(name,age){ this.age = age People.call(this,name)// 第一次調(diào)用 } Child3.prototype = new People('xiaoming')//第二次調(diào)用 People.prototype.constructor = People let xiaoming = new Child3('xiaoming',18) console.log(xiaoming.name,xiaoming.age) // xiaoming 18
-
原型式繼承
把一個(gè)對(duì)象作為另一個(gè)對(duì)象的基礎(chǔ),通過(guò)一個(gè)中介構(gòu)造函數(shù)去創(chuàng)建一個(gè)實(shí)例陆盘。
// 方式1 function object(o) { var F = function(){} F.prototype = o return new F() } var person2 = object(obj) // 方式2 var person1 = Object.create(obj, { name: { value: 'person1' }})
-
寄生式繼承
創(chuàng)建一個(gè)用來(lái)封裝繼承過(guò)程的函數(shù)普筹,在該函數(shù)的內(nèi)部通過(guò)某種方式來(lái)增強(qiáng)對(duì)象,然后返回這個(gè)對(duì)象隘马。
可以將最開(kāi)始的對(duì)象擴(kuò)展后,返回被繼承
通原型鏈繼承一樣,此時(shí)無(wú)法獲取到構(gòu)造函數(shù)屬性
寄生繼承直接指向父類的
prototype
,所以不會(huì)重復(fù)調(diào)用父類的情況
let obj = { name: '小明', age: 18, like: ['吃飯', '睡覺(jué)'] } function createFn(ob) { let o = Object.create(ob) o.sayHi = function () { console.log('hi') } return o } let child4 = createFn(obj) console.log(child4.name,child4.age)// 小明 18
-
寄生組合繼承
通過(guò)借用構(gòu)造函數(shù)方式繼承屬性太防,通過(guò)原型鏈混成方式繼承方法
通過(guò)寄生的方式來(lái)修復(fù)組合式繼承的不足,完美的實(shí)現(xiàn)繼承
People.prototype.eat = function () { console.log('吃飯') } //子類 function Man(name,age) { People.call(this,name) this.age = age } //繼承父類的方法 function createFn(father,child) { let o = Object.create(father.prototype) console.log(o) o.constructor = child child.prototype = o } createFn(People, Man) let person1 = new Man('xiaoming',18) console.log(person1.name,person1.age)// xiaoming 18
-
ES6繼承
class People { constructor(name ,age){ this.name = name this.age = age } like () { console.log('吃飯','睡覺(jué)') } } class Man extends People { constructor(name,age){ //繼承父類屬性 super(name,age) } like () { super.like() } } let people = new Man('xiaoming',18) console.log(people.name,people.age)//xiaoming 18 people.like()