用ES5實現(xiàn)繼承拙毫,就是用原型鏈實現(xiàn)。只要把子類和父類的原型鏈打通就解決了主要問題棺禾。最常用的是組合繼承:
1恬偷、先看第1個關(guān)鍵語句
Father.call(this, age)
。這句話的作用很明顯帘睦,是在Child()執(zhí)行時袍患,當執(zhí)行到Father()就把this強行綁定到Child函數(shù)的上下文。我們知道函數(shù)內(nèi)用聲明在this下的屬性/方法竣付,是屬于實例的诡延,和this相關(guān)的就只和實例相關(guān)。在這里實例化new Child(30,”上海浦東”) 的時候古胆,this.age=age執(zhí)行時this指向Child的實例肆良,所以最終Child的實例既擁有age屬性又擁有address筛璧,也就是說子類的實例得到(繼承)了父類的屬性。Father.call(this, age)解決了屬性/方法定義在實例上的情形惹恃,那么下兩句關(guān)鍵語句解決的就是屬性/方法定義在函數(shù)原型上的情形夭谤。
2、看第2個關(guān)鍵語句
Child.prototype=new Father()
巫糙。這句話首先創(chuàng)建了一個父類實例朗儒,此時這個Father父類的實例是{age:undefined}
對象;然后讓Child.prototype指向這個對象参淹,Child.prototype是干嘛的醉锄,默認情況下Child.prototype可是Child所有實例的原型,把它指向Father的實例意義就是讓Child的所有實例的原型指向Father的某一個實例(或者說讓Father的一個實例成為Child所有實例的原型)浙值。那么Child子類的實例就可以順著原型鏈訪問到屬于Father原型上的屬性/方法了恳不。原型鏈如下圖:Child.prototype.constructor=Child
是個細節(jié)开呐。默認情況下Child.prototype.constructor就是等于Child的(Child.prototype是{constructor:f}
這么一個對象)烟勋,而第2個關(guān)鍵語句Child.prototype=new Father()執(zhí)行完,Child.prototype就被改變了筐付,此時上面instance的constructor就會是Father卵惦,子類實例的構(gòu)造器怎么能是父類呢,顯然不對家妆。所以需要顯式的給constructor重新賦值Child。題外話冕茅,為什么instance.constructor會是Father呢伤极?constructor默認是構(gòu)造函數(shù)獨有的屬性,也就是普通對象是沒有的姨伤,instance是
{age:30,address:”上海浦東”}
對象哨坪,不是函數(shù),所以沒有constructor乍楚,就要去它原型上找当编,原型是new Father()出來的對象,也不是函數(shù)徒溪,就要再去上一級原型上找忿偷,也就是去Father.prototype上找,而Father.prototype.constructor就是Father臊泌。