關於js繼承的理解與實現

繼承方式一:函數

function P1(){
    this.name = "nn";
   this.eat = function(){
    console.log("I am eating!")
   } } P1.prototype.say = function(){
  console.log("say Hi!")
}
function C1(){   this.type = "tt";   this.arr = [1,2,3];
  P1.call(this) }
var c1 = new C1();
console.log(c1.name); // nn
console.log(c1.eat()); // I am eating!
console.log(c1.say()); //報錯 Uncaught TypeError: c1.say is not a function
因而可知,這種方式下能夠繼承父類自身的的屬性和方法,不能繼承原型鏈上的屬性和方法
 

繼承方式二:this

function P2(){
     this.name = "nn";
     this.arr = [1,2,3];
     this.eat = function(){
         console.log("I am eating!");
     }
  }
  P2.prototype.say = function(){
    console.log("say Hi!");
 }
 function C2(){
   this.type = "tt"; 
 }
 C2.prototype = new P2();
 
 var c2 = new C2();
var c21 = new C2();

console.log(c2.name) // nn

console.log(c2.eat()) // I am eating!
console.log(c2.say()); // say Hi!
c2.arr.push(4);
console.log(c2.arr) // [1,2,3,4]
console.log(c21.arr); // [1,2,3,4]

因而可知,C2經過protopype把P2做爲他的原型鏈,實現了繼承,繼承了P2的全部屬性和方法,可是有一個問題就是對於引用的數據類型,一旦其中一個實例對引用類型改變,全部的實例化對象的引用類型值也改變了,就像是例子中的arr

繼承方式三:spa

function P3(){
     this.name = "nn";
     this.arr = [1,2,3];
     this.eat = function(){
         console.log("I am eating!");
     }
  }
  P3.prototype.say = function(){
    console.log("say Hi!");
 }
 function C3(){
   this.type = "tt"; 
       P3.call(this)
 }
 C3.prototype = new P3();
 
 var c3 = new C3();
 var c31 = new C3();

console.log(c3.name) // nn

console.log(c3.eat()) // I am eating!
console.log(c3.say()); // say Hi!
c3.arr.push(4);
console.log(c3.arr) // [1,2,3,4]
console.log(c31.arr); // [1,2,3]

爲了解決2中出現的問題,利用了 P3.call(this) 這個方法,使得在每一個實例自己都有父親的全部屬性和方法,而不是去取原型鏈上的引用類型

繼承方式四:prototype

function P4(){
     this.name = "nn";
     this.arr = [1,2,3];
     this.eat = function(){
         console.log("I am eating!");
     }
  }
  P4.prototype.say = function(){
    console.log("say Hi!");
 }
 function C4(){
   this.type = "tt"; 
       P4.call(this)
 }
 C4.prototype = P4.prototype;
 
 var c4 = new C4();
 var c41 = new C4();

這種方法看起來已經解決上面遇到的全部問題,
方式一的不能繼承父元素的原型鏈上的方法,
方式二的修改原型鏈上引用類型會修改該全部實例的問題,
方法三的重複的實例化構造函數的問題,
可是其實方式二,三,四都還有一個問題,就是他們沒法去判斷誰是子元素的直接父元素,
instanceof只能判斷構該構造函數的實例在這條原型鏈上,好比c4 instanceof P4 結果爲true,c4 instanceof Object的結果也爲 true
實際上 C4.prototype.constructor === P4 爲 true
爲了解決這個問題 能夠參考方式五

繼承方式五:code

function P5(){
     this.name = "nn";
     this.arr = [1,2,3];
     this.eat = function(){
         console.log("I am eating!");
     }
  }
  P4.prototype.say = function(){
    console.log("say Hi!");
 }
 function C5(){
   this.type = "tt"; 
       P5.call(this)
 }
 C5.prototype = Object.create(P5.prototype);
 C5.prototype.constructor = C5
var c5 = new C5(); var c51 = new C5();

備註:使用Object.create()建立的js對象,沒有constructor

好了,這就是對原型鏈以及繼承的理解與實現,後續有新內容再繼續補充!對象

相關文章
相關標籤/搜索