利用call和原型對象實現繼承函數
1 //3.利用call和原型對象實現繼承 2 //父構造函數 3 function Father(name,age){ 4 //this指向父構造函數的對象實例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //給父親添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100萬!') 14 } 15 //子構造函數 16 function Son(name,age,score){ 17 //調用父構造函數,並修改Father的this爲兒子的this,以達到調用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 var wb = new Son('小王八',8,100) 22 console.log(wb);
運行結果:測試
能夠看到利用call能夠修改父親函數的this,使它變成子函數的this,然而繼承過來的只有父親函數裏面定義的方法,父親而外經過原型對象添加的方法,this
兒子並不可使用,與咱們想的繼承仍是有所出入,那麼這麼解決呢?spa
直接把父親的原型賦值給兒子好嗎?prototype
1 //3.利用call和原型對象實現繼承 2 //父構造函數 3 function Father(name,age){ 4 //this指向父構造函數的對象實例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //給父親添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100萬!') 14 } 15 //子構造函數 16 function Son(name,age,score){ 17 //調用父構造函數,並修改Father的this爲兒子的this,以達到調用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 Son.prototype = Father.prototype ; 22 var wb = new Son('小王八',8,100) 23 var f = new Father('爸爸',50) 24 console.log(wb); 25 console.log(f)
運行截圖:3d
咱們能夠看到父親和兒子的對象原型_proto_好像都有了money,那是否是兒子成功繼承了父親的函數了呢?code
可是因爲父親有本身的函數,那麼兒子也要有本身的函數,好比考試,咱們給兒子添加考試函數對象
//3.利用call和原型對象實現繼承 //父構造函數 function Father(name,age){ //this指向父構造函數的對象實例 this.name = name ; this.age = age; this.sing = function(){ console.log('sing') } } //給父親添加了money方法 Father.prototype.money=function(){ console.log('100萬!') } //子構造函數 function Son(name,age,score){ //調用父構造函數,並修改Father的this爲兒子的this,以達到調用父方法 Father.call(this,name,18); this.score = score; } Son.prototype = Father.prototype ;//把父親的原型賦值給兒子 //給兒子的原型添加本身的方法 Son.prototype.exam = function(){ console.log('w我考了100分!') } var wb = new Son('小王八',8,100) var f = new Father('爸爸',50) console.log(wb); console.log(f)
運行結果:blog
從結果上面看,咱們發現果真兒子要考試,添加成功,可是仔細一看,爸爸也要考試了!繼承
爲何會這樣呢,看下圖
由於咱們上面直接把父親的原型對象給了兒子,其實至關於把地址直接賦給兒子了,那麼兒子若是改了什麼,父親也會隨之改動,不符合繼承的性質。
正確方法:
1 //3.利用call和原型對象實現繼承 2 //父構造函數 3 function Father(name,age){ 4 //this指向父構造函數的對象實例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //給父親添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100萬!') 14 } 15 //子構造函數 16 function Son(name,age,score){ 17 //調用父構造函數,並修改Father的this爲兒子的this,以達到調用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 //Son.prototype = Father.prototype ;//把父親的原型賦值給兒子有問題,此處爲地址賦值,會引起錯誤 22 Son.prototype = new Father(); 23 //給兒子的原型添加本身的方法 24 Son.prototype.exam = function(){ 25 console.log('w我考了100分!') 26 } 27 var wb = new Son('小王八',8,100) 28 var f = new Father('爸爸',50) 29 console.log(wb); 30 console.log(f)
運行結果:
咱們看到兒子可使用父親的函數,也有了本身獨特的函數。
上面實際修改了 Son.prototype = Father.prototype ;
修改後變成:Son.prototype = new Father(),實際操做以下:只是拿到了Father的實例對象,而後fanther的實例對象能夠拿到father原型對象的money方法,
並且兒子添加本身的方法最多修改了father的實例對象,父親的構造函數沒有影響。
可是上面仍是有問題,由於Son.prototype = new Father(),把Father的實例對象賦值給了兒子,看似全部東西都解決了,
可是兒子裏面的constructor指向父親的構造函數了,因此還需修改兒子的constructor指向本身的構造函數。
1 //3.利用call和原型對象實現繼承 2 //父構造函數 3 function Father(name,age){ 4 //this指向父構造函數的對象實例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //給父親添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100萬!') 14 } 15 //子構造函數 16 function Son(name,age,score){ 17 //調用父構造函數,並修改Father的this爲兒子的this,以達到調用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 //Son.prototype = Father.prototype ;//把父親的原型賦值給兒子有問題,此處爲地址賦值,會引起錯誤 22 Son.prototype = new Father();//把父親實例對象賦給兒子 23 //把對象賦給兒子後,兒子的constructor也指向父親了,須要手動指回兒子 24 //給兒子的原型添加本身的方法 25 Son.prototype.exam = function(){ 26 console.log('w我考了100分!') 27 } 28 var wb = new Son('小王八',8,100) 29 var f = new Father('爸爸',50) 30 console.log(wb); 31 console.log('---------------開始測試----------------------') 32 console.log('------修改前兒子的constructor指向-------------') 33 console.log(Son.prototype.constructor) 34 Son.prototype.constructor = Son;//修改指向 35 console.log('------修改後兒子的constructor指向-------------') 36 console.log(Son.prototype.constructor) 37 console.log('---------------結束測試----------------------') 38 console.log(f)
運行結果:
固然這裏很麻煩,由於是Es5的時候寫繼承必須這樣,Es6就簡單了!