javascript學習筆記(20)--class繼承

引入

在上面的章節中我們看到了JavaScript的對象模型是基於原型實現的,特點是簡單,缺點是理解起來比傳統的類-實例模型要困難,最大的缺點是繼承的實現需要編寫大量代碼,並且需要正確實現原型鏈

新的關鍵字class從ES6開始正式被引入到JavaScript中
class的目的就是讓定義類更簡單

class

還是先回顧一下之前的方法

function Student(name){
this.name=name;
this.hello=function(){console.log('你好');};
Student.prototype.id=1;
Student.prototype.greet=function(){console.log('i am ok');};
}

因爲我們在定義類的時候主要關注兩個,一個是實例,一個是prototype,而用函數的化,this定義的實例,prototype定義就不用說了
我們可以通過實例化後的對象看他身上具有的實例和prototype屬性方法
在這裏插入圖片描述
先講講class的規矩
在這裏插入圖片描述不能直接定義函數(沒有function關鍵字)
在這裏插入圖片描述也不能直接定義實例變量
在這裏插入圖片描述
也不能直接在prototype下定義變量(雖然之前函數可以,但其實最好還是在定義完之後再引入)
在這裏插入圖片描述
不能重複定義class

class裏面直接引入了構造函數,並且爲了方便在prototype下定義函數,我們直接 f(){};這樣寫就可以,就表明你的函數是在prototype下面啦,就避免了Student.prototype.f= function () {…}這樣分散的代碼

先上個簡單的class類

 class Student { 
 constructor(name) { 
 this.name = name; 
 this.hello=function(){console.log('你好');};
 }
 id=1;
 greet(){console.log('i am ok');};
 }

在這裏插入圖片描述
可以看到,我們定義的函數都是在prototype下,在class裏直接定義的變量也是屬於實例變量,然後在constructor裏定義的變量和函數其實和之前函數裏的差不多,也是實例屬性(其實constructor和我們前面的構造函數差不多)

最開始還沒發現,其實constructor和構造函數都是一摸一樣的,剛纔不是說嘛,在class內部不能直接定義prototype,我們可以轉移到constructor內部

class Student { 
 constructor(name) { 
 this.name = name; 
 this.hello=function(){console.log('你好');};Student.prototype.grade=1;Student.prototype.lalala=function(){console.log('啦啦啦');};
 }
 id=1;
 greet(){console.log('i am ok');};
 }
Student.prototype.grade=1;//這個放在整體定義完之後也可以

在這裏插入圖片描述怎麼樣,確實是和我們之前講的構造函數一摸一樣吧

class外部定義的實例變量(id=1)和pr函數 和construcotr裏面的有什麼區別嗎
之前的構造函數可以直接把protype變成null,但class的prototype真的是
在這裏插入圖片描述改不動,但裏面的內容還是可以修改的
不過跟構造函數的一樣,construcotr修改了沒用
在這裏插入圖片描述
像constroctor裏面的this綁定的變量方法和外面的id又都是實例變量方法,也改不了

像是prototype下綁定的內容修改了後還是要注意新創建對象的時候重新賦值的問題

在這裏插入圖片描述在這裏插入圖片描述
所以其實沒什麼區別,定義到哪裏都可以…都是一樣的
但其實還是有一點細微的區別,如果你定義的實例化變量是需要傳入參數的,就只能放在constructor裏面(prototype裏一般不會出現需要賦值的變量,不然那其實最後還是變成實例變量了),像如果你直接放在class的話無法傳入參數的

最後,創建一個Student對象代碼和前面章節完全一樣

var xiaoming = new Student('小明'); 
xiaoming.hello();

class繼承

用class定義對象的另一個巨大的好處是繼承更方便了
想一想我們從Student派生一個PrimaryStudent需要編寫的代碼量,現在,原型繼承的中間對象,原型對象的構造函數等等都不需要考慮了,直接通過extends來實現

 class Student { 
 constructor(name) { 
 this.name = name; 
 this.hello=function(){console.log('你好');};Student.prototype.age=1;Student.prototype.lalala=function(){console.log('啦啦啦');};
 }
 }
 
 class PrimaryStudent extends Student 
 {
  constructor(name, grade) 
 { super(name); 
 this.grade = grade;
  }
  myGrade() { alert('我的分數是' + this.grade); } }

注意PrimaryStudent的定義也是class關鍵字實現的,而extends則表示原型鏈對象來自Student
子類的構造函數可能會與父類不太相同,例如,PrimaryStudent需要name和grade兩個參數,並且需要通過super(name)來調用父類的構造函數,否則父類的name屬性無法正常初始化,而另一個就是我們自己新定義的變量
PrimaryStudent已經自動獲得了父類Student的一系列方法,我們又在子類中定義了新的myGrade方法
在這裏插入圖片描述
在這裏插入圖片描述還是可以看出來的,Student和Primary裏面定義的所有實例變量和方法都變成了實例化對象裏的實例變量和方法
定義在Primary.prototype裏的方法和屬性和Studentprototype裏的屬性和方法也統統被繼承了下來

好了這部分算是結束了,最後幾個是js裏面最複雜的了,接下來咱們正式進入瀏覽器 ,希望大家多多支持

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章