溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JavaScript中實(shí)現(xiàn)繼承的方法有哪些

發(fā)布時(shí)間:2021-02-09 11:45:35 來(lái)源:億速云 閱讀:164 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章為大家展示了JavaScript中實(shí)現(xiàn)繼承的方法有哪些,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

借用構(gòu)造函數(shù)

這種技術(shù)的基本思想很簡(jiǎn)單,就是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型的構(gòu)造函數(shù)。另外,函數(shù)只不過(guò)是在特定環(huán)境中執(zhí)行代碼的對(duì)象,因此通過(guò)使用apply()和call()方法也可以在新創(chuàng)建的對(duì)象上執(zhí)行構(gòu)造函數(shù)。

function Box(name){
 this.name = name
}
Box.prototype.age = 18

function Desk(name){
 Box.call(this, name) // 對(duì)象冒充,對(duì)象冒充只能繼承構(gòu)造里的信息
}

var desk = new Desk('ccc')
console.log(desk.name)   // --> ccc
console.log(desk.age)    // --> undefined

從中可以看到,繼承來(lái)的只有實(shí)例屬性,而原型上的屬性是訪問(wèn)不到的。這種模式解決了兩個(gè)問(wèn)題,就是可以傳參,可以繼承,但是沒有原型,就沒有辦法復(fù)用。

組合繼承

function Box(name){
 this.name = name
}
Box.prototype.run = function (){
 console.log(this.name + '正在運(yùn)行...')
}

function Desk(name){
 Box.call(this, name) // 對(duì)象冒充
}

Desk.prototype = new Box() // 原型鏈

var desk = new Desk('ccc')
console.log(desk.name)   // --> ccc
desk.run()         // --> ccc正在運(yùn)行...

這種繼承方式的思路是:用使用原型鏈的方式來(lái)實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,而通過(guò)借用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。

原型式繼承

原型式繼承:是借助原型可以基于已有的對(duì)象創(chuàng)建新對(duì)象,同時(shí)還不必因此創(chuàng)建自定義類型。講到這里必須得提到一個(gè)人,道格拉斯·克羅克福德在2006年寫的一篇文章《Prototype inheritance in Javascript》(Javascript中的原型式繼承)中給出了一個(gè)方法:

function object(o) {   //傳遞一個(gè)字面量函數(shù)
 function F(){}     //創(chuàng)建一個(gè)構(gòu)造函數(shù)
 F.prototype = o;    //把字面量函數(shù)賦值給構(gòu)造函數(shù)的原型
 return new F()     //最終返回出實(shí)例化的構(gòu)造函數(shù)
}

看如下的例子:

function obj(o) {
 function F (){}
 F.prototype = o;
 return new F()
}

var box = {
 name: 'ccc',
 age: 18,
 family: ['哥哥','姐姐']
}

var box1 = obj(box)
console.log(box1.name)   // --> ccc
box1.family.push('妹妹')
console.log(box1.family)  // --> ["哥哥", "姐姐", "妹妹"]

var box2 = obj(box)
console.log(box2.family)  // --> ["哥哥", "姐姐", "妹妹"]

因?yàn)樯鲜龅拇a的實(shí)現(xiàn)邏輯跟原型鏈繼承很類似,所以里面的引用數(shù)組,即family屬性被共享了。

寄生式繼承

function obj(o) {
 function F (){}
 F.prototype = o;
 return new F()
}
function create(o){
 var clone = obj(o)   // 通過(guò)調(diào)用函數(shù)創(chuàng)建一個(gè)新對(duì)象
 clone.sayName = function(){   // 以某種方式來(lái)增強(qiáng)這個(gè)對(duì)象
  console.log('hi')
 }
 return clone   // 返回這個(gè)對(duì)象
}

var person = {
 name: 'ccc',
 friends: ['aa','bb']
}

var anotherPerson = create(person)
anotherPerson.sayName()   // --> hi

這個(gè)例子中的代碼基于person返回一個(gè)新對(duì)象————anotherPerson。新對(duì)象不僅具有person的所有屬性和方法,而且還有自己的sayHi()方法。在主要考慮對(duì)象而不是自定義類型和構(gòu)造函數(shù)的情況下,寄生式繼承也是一種有用的模式。使用寄生式繼承來(lái)為對(duì)象添加函數(shù),會(huì)由于不能做到函數(shù)復(fù)用而降低效率,這一點(diǎn)與構(gòu)造函數(shù)模式類似。

寄生組合式繼承

前面說(shuō)過(guò),組合繼承是Javascript最常用的繼承模式,不過(guò),它也有自己的不足。組合繼承最大的問(wèn)題就是無(wú)論什么情況下,都會(huì)調(diào)用過(guò)兩次超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時(shí)候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部。沒錯(cuò),子類型最終會(huì)包含超類型對(duì)象的全部實(shí)例屬性,但我們不得不在調(diào)用子類型構(gòu)造函數(shù)時(shí)重寫這些屬性,再來(lái)看一下下面的例子:

function SuperType(name){
 this.name = name;
 this.colors = ['red','black']
}
SuperType.prototype.sayName = function (){
 console.log(this.name)
}
function SubType(name, age){
 SuperType.call(this, name) // 第二次調(diào)用SuperType
 this.age = age
}

SubType.prototype = new SuperType() // 第一次調(diào)用SuperType
SubType.prototype.constructor = SubType
SubType.prototype.sayAge = function (){
 console.log(this.age)
}

第一次調(diào)用SuperType構(gòu)造函數(shù)時(shí),SubType.prototype會(huì)得到兩個(gè)屬性:name和colors。他們都是SuperType的實(shí)例屬性,只不過(guò)現(xiàn)在位于SubType的原型中。當(dāng)調(diào)用SubType構(gòu)造函數(shù)時(shí),又會(huì)調(diào)用一次SuperType構(gòu)造函數(shù),這個(gè)一次又在新對(duì)象上創(chuàng)建了實(shí)例屬性name和colors。于是,這兩個(gè)屬性就屏蔽了原型中的兩個(gè)同名屬性。即有兩組name和colors屬性:一組在實(shí)例上,一組在原型上。這就是調(diào)用兩次SuperType構(gòu)造函數(shù)的結(jié)果。解決這個(gè)問(wèn)題的方法就是————寄生組合式繼承。
所謂寄生組合式繼承,即通過(guò)借用構(gòu)造函數(shù)來(lái)繼承屬性,通過(guò)原型鏈的混成形式來(lái)繼承方法。其背后的基本思路是:不必為了制定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù),我們所需要的無(wú)非就是超類型原型的一個(gè)副本而已。本質(zhì)上,就是使用寄生式繼承來(lái)繼承超類型的原型,然后再將結(jié)果指定給子類型的原型。寄生組合式繼承的基本模式如下:

function object(o) {
 function F (){}
 F.prototype = o;
 return new F()
}
function inheritPtototype(subType, superType){
 var prototype = object(superType.prototype) // 創(chuàng)建對(duì)象
 prototype.constructor = subType       // 增強(qiáng)對(duì)象
 subType.prototype = prototype        // 指定對(duì)象
}

function SuperType(name){
 this.name = name
 this.colors = ['red', 'white']
}

SuperType.prototype.sayName = function(){
 console.log(this.name)
}

function SubType(name,age){
 SuperType.call(this,name)
 this.age = age
}

inheritPtototype(SubType, SuperType)

SubType.prototype.sayAge = function(){
 console.log(this.age)
}

var instance = new SubType('ccc', 18)

instance.sayName()   // --> ccc
instance.sayAge()    // --> 18
console.log(instance)

控制臺(tái)打印出的結(jié)構(gòu):

JavaScript中實(shí)現(xiàn)繼承的方法有哪些

詳細(xì)的圖解:

JavaScript中實(shí)現(xiàn)繼承的方法有哪些

上述內(nèi)容就是JavaScript中實(shí)現(xiàn)繼承的方法有哪些,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI