ES裏面沒有真正的繼承,可是能經過某些手段達到繼承效果,從而讓一個類擁有另一個類的方法 類 =>構造函數app
繼承描述某語言環境---魔獸世界 哈!其實我沒玩過 魔獸世界裏面 有Humen類 Humen類裏面有Gnome(侏儒) , gnome有方法say(個人名字)
有共有屬性ggroup=gnome ,humen 有共有屬性hgroup=humen , 有本身名字 hname 共有方法write();函數
總共共3種繼承方式 一種類繼承 一種是原型繼承 還有一種組合繼承 至於其餘的繼承方式,本質上沒啥區別this
function humen(name){ //人類類 this.name=name; this.write=function(){ console.log("write") } } humen.prototype.hgroup="humen"; new humen('張三'); //傳統的是在gnome裏面創建一個temp屬性 指向humen構造函數,從而去用humen裏面this指向ganme 而後去初始化gnome裏面的屬性和方法(略) /**下面是類繼承 */ function gnome(name){ this.say=function(){ console.log(this.name); }; humen.call(this,name); } gnome.prototype.ggroup="gnome"; var gnome=new gnome("李四"); console.log(gnome.name); //"李四" console.log(gnome.hgroup);//"underfined" 由此能夠得出這種繼承方式只是借用call 或者apply 來改變this 借用構造函數初始化屬性和方法 //沒法繼承原型上面的屬性和方法 /*************************下面是原型繼承 ***********************/ function gnome(name){ this.name=name; this.say=function(){ console.log(this.name); } } gnome.prototype.ggroup="gnome"; gnome.prototype=new humen(); // 這裏把一些公共的參數傳進去。。。 var gnome=new gnome("李四"); gnome.say();//李四 console.log(gnome.hgroup); //humen 由此得出這種繼承方式可以繼承原型鏈上面的屬性和方法 可是個體的方法(this.name)須要從新寫一遍 /*************************都用的不爽 前面2種一種不能繼承原型 一種構造函數裏面的屬性須要從新定義 混合繼承***********************/ function gnome(name){ this.say=function(){ //本身的方法 console.log(this.name); }; humen.call(this,name); } gnome.prototype=new humen(); //new humen裏面name屬性是undefined 被類繼承的name覆蓋 gnome.prototype.ggroup="gnome"; var gnome1=new gnome("李四"); gnome1.say();//李四 gnome.prototype.constructor=gnome; //因爲用原型繼承 構造函數方向指向humen console.log(gnome1.hgroup);//"humen" console.log(gnome1.ggroup); //"gnome"
總結:每使用new 關鍵字new一個對象都是在建立一個空對象,改變this指針指向空對象,而後初始化其中屬性和方法,還有_proto_指向原型對象,因此對於一些公用的屬性和方法定義在原型對象之中,避免浪費內存,私有的(與參數相關)則放在構造函數中。類繼承和原型繼承都有各自的弊端,組合繼承則互補,實現完美繼承,注意constructor的指向spa
另外附上某處偷來的,本身以爲比較好的js世界裏面的原型鏈圖:prototype