繼承的概念
繼承:子類可以訪問父類的所有屬性和方法,并且可以對這些屬性和方法進行擴展
繼承的幾種方式
-
原型鏈繼承
利用原型讓一個對象繼承另一個對象的屬性和方法,,即把一個對象的原型作為另一個對象的實例,這樣就可以繼承另一個對象的屬性和方法
優(yōu)點:
- 簡單易于實現(xiàn),父類的新增的實例與屬性子類都能訪問
缺點:
- 子類更改從父類繼承過來的引用類型的屬性,由于原型屬性中的引用類型屬性會被所有實例共享,因此會影響其他實例
- 創(chuàng)建子類實例時,沒有辦法在不影響其他實例的情況下向超類型的構(gòu)造函數(shù)中傳參、
- 可以在子類中增加實例屬性,如果要新增加原型屬性和方法需要在new 父類構(gòu)造函數(shù)的后面
- 無法實現(xiàn)多繼承、
- 創(chuàng)建子類實例時,不能向父類構(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)部通過call或apply去繼承超類型屬性或方法
優(yōu)點:
- 解決了子類構(gòu)造函數(shù)向父類構(gòu)造函數(shù)中傳遞參數(shù)
- 可以實現(xiàn)多繼承(call或者apply多個父類)
缺點:
- 方法都在構(gòu)造函數(shù)中定義,無法復(fù)用
- 不能繼承原型屬性/方法,只能繼承父類的實例屬性和方法
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 -
組合繼承
使用原型鏈實現(xiàn)原型屬性和方法的繼承,使用借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承
優(yōu)點:
- 函數(shù)可以復(fù)用
- 不存在引用屬性問題
- 可以繼承屬性和方法,并且可以繼承原型的屬性和方法
缺點: 需要調(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 -
原型式繼承
把一個對象作為另一個對象的基礎(chǔ),通過一個中介構(gòu)造函數(shù)去創(chuàng)建一個實例。
// 方式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)建一個用來封裝繼承過程的函數(shù),在該函數(shù)的內(nèi)部通過某種方式來增強對象,然后返回這個對象。
可以將最開始的對象擴展后,返回被繼承
通原型鏈繼承一樣,此時無法獲取到構(gòu)造函數(shù)屬性
寄生繼承直接指向父類的
prototype,所以不會重復(fù)調(diào)用父類的情況
let obj = { name: '小明', age: 18, like: ['吃飯', '睡覺'] } 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 -
寄生組合繼承
通過借用構(gòu)造函數(shù)方式繼承屬性,通過原型鏈混成方式繼承方法
通過寄生的方式來修復(fù)組合式繼承的不足,完美的實現(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('吃飯','睡覺') } } 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()