ReactNative填坑之旅–class(番外篇)

行者武松發表於2017-08-01

無論React還是RN都已經邁入了ES6的時代,甚至憑藉Babel的支援都進入了ES7。ES6內容很多,本文主要講解類相關的內容。

建構函式

定義偵探類作為例子。

ES5的“類”是如何定義的。


  1. function ES5Detective() { 
  2.   console.log(`##ES5Detective contructor`); 
  3. }  

ES6定義類:


  1. class ES6Detective { 
  2.   constructor() { 
  3.     console.log(`Detective constructor`); 
  4.   } 
  5. }  

ES6使用了class關鍵字,而且有專門的constructor。ES5裡的function ES5Detective既是類的定義,也是建構函式。

屬性

看看這個偵探是從哪本書出來的。

ES5:


  1. ES5Detective.prototype.fromBookName = `who`

ES6:


  1. class ES6Detective { 
  2.   detectiveName: string; 
  3.   _bookName: string; 
  4.  
  5.   constructor() { 
  6.     console.log(`Detective constructor`); 
  7.     this.detectiveName = `Detective who`; // 屬性 
  8.   } 
  9. }  

ES6 getter & setter


  1. class ES6Detective { 
  2.   detectiveName: string; 
  3.   _bookName: string; 
  4.  
  5.   constructor() { 
  6.     console.log(`Detective constructor`); 
  7.     this.detectiveName = `Detective who`
  8.     this._bookName = `who`
  9.   } 
  10.  
  11.   get fromBookName() { 
  12.     return this._bookName; 
  13.   } 
  14.  
  15.   set fromBookName(value) { 
  16.     this._bookName = value; 
  17.   } 
  18. }  

如果只有getter沒有setter而賦值的話就會出現下面的錯誤:


  1. detective.bookAuthor = `A C`
  2.                      ^ 
  3.  
  4. TypeError: Cannot set property bookAuthor of #<ES6Detective> which has only a getter  

例項方法

偵探是如何解決案件的。

ES5:


  1. ES5Detective.prototype.solveCase = function(caseName) { 
  2.   var dn = this.dectiveName; 
  3.   if(!caseName) { 
  4.     console.log(`SOLVE CASE: ` + dn + ` no case to solve`); 
  5.   } else { 
  6.     console.log(`SOLVE CASE: ` + dn + ` get case ` + caseName + ` is solved`); 
  7.   } 
  8. };  

或者:


  1. function ES5Detective() { 
  2.   this.dectiveName = `Detective who`
  3.   console.log(`##ES5Detective contructor`); 
  4.   // 例項方法 
  5.   this.investigate = function(scene) { 
  6.     console.log(`investigate ` + scene); 
  7.   } 
  8.  
  9.   this.assistant = “assistant who”
  10. }  

ES6:


  1. class ES6Detective { 
  2.   detectiveName: string; 
  3.   _bookName: string; 
  4.  
  5.   constructor() { 
  6.     console.log(`Detective constructor`); 
  7.     this.detectiveName = `Detective who`
  8.     this._bookName = `who`
  9.   } 
  10.  
  11.   solveCase(caseName) { 
  12.     if(!caseName) { 
  13.       console.log(`no case to solve`); 
  14.     } else { 
  15.       console.log(`case ` + caseName + ` is solved`); 
  16.     } 
  17.   } 
  18. }  

ES6新增方法非常簡單直接。ES5中新增例項方法有兩種方法,一是在prototype裡定義,一是在建構函式重定義。在建構函式中定義的例項方法和屬性在每一個例項中都會保留一份,而在原型中定義的例項方法和屬性是全部例項只有一份。

另外,在ES5的建構函式重定義的例項方法可以訪問類的私有變數。比如:


  1. function ES5Detective() { 
  2.   console.log(`##ES5Detective contructor`); 
  3.  
  4.   var available: boolean = true; // private field. default income is ZERO. 
  5.   this.investigate = function(scene) { 
  6.     if (available) { 
  7.       console.log(`investigate ` + scene); 
  8.     } else { 
  9.       console.log(`i`m not available`); 
  10.     } 
  11.   } 
  12. }  

在其他的方法訪問的時候就會報錯。


  1. if (!available) { 
  2.  
  3. ^  

靜態方法

ES5:


  1. ES5Detective.countCases = function(count) { 
  2.   if(!count) { 
  3.     console.log(`no case solved`); 
  4.   } else { 
  5.     console.log(`${count} cases are solved`); 
  6.   } 
  7. };  

類名後直接定義方法,這個方法就是靜態方法。


  1. ES5Detective.countCases(); 

ES6:


  1. class ES6Detective { 
  2.   static countCases() { 
  3.     console.log(`Counting cases…`); 
  4.   } 
  5.  
  6. // call it 
  7. ES6Detective.countCases();  

繼承

ES6使用extends關鍵字實現繼承。

ES5:


  1. function ES5Detective() { 
  2.   var available: boolean = true; // private field. 
  3.  
  4.   this.dectiveName = `Detective who`
  5.   console.log(`##ES5Detective contructor`); 
  6.  
  7.   this.investigate = function(scene) { 
  8.     // 略  
  9.   } 
  10.  
  11.   this.assistant = “assistant who”
  12.  
  13. ES5Detective.prototype.solveCase = function(caseName) { 
  14.   // 略 
  15.  
  16. // inheritance 
  17. function ES5DetectiveConan() { 
  18.   // first line in constructor method is a must!!! 
  19.   ES5Detective.call(this); 
  20.  
  21.   this.dectiveName = `Conan`
  22.  
  23. // inheritance 
  24. ES5DetectiveConan.prototype = Object.create(ES5Detective.prototype); 
  25. ES5DetectiveConan.prototype.constructor = ES5DetectiveConan;  

ES5繼承的時候需要注意兩個地方:

  1. 需要在子類的建構函式裡呼叫SuperClass.call(this[, arg1, arg2, …])
  2. 子類的prototype賦值為:SubClass.prototype =
    Object.create(SuperClass.prototype),然後把建構函式重新指向自己的:SubClass.prototpye.constructor
    = SubClass。

ES6:


  1. class ES6Detective { 
  2.   constructor() { 
  3.     console.log(`Detective constructor`); 
  4.     this.detectiveName = `Detective who`
  5.     this._bookName = `who`
  6.   } 
  7.  
  8.   solveCase(caseName) { 
  9.     if(!caseName) { 
  10.       console.log(`no case to solve`); 
  11.     } else { 
  12.       console.log(`case ` + caseName + ` is solved`); 
  13.     } 
  14.   } 
  15.  
  16.   get fromBookName() { 
  17.     return this._bookName; 
  18.   } 
  19.  
  20.   set fromBookName(value) { 
  21.     this._bookName = value; 
  22.   } 
  23.  
  24.   get bookAuthor() { 
  25.     return `Author Who`
  26.   } 
  27.  
  28.   static countCases() { 
  29.     console.log(`Counting cases…`); 
  30.   } 
  31.  
  32. class ES6DetectiveConan extends ES6Detective { 
  33.   constructor() { 
  34.     super(); 
  35.     console.log(`ES6DetectiveConan constructor`); 
  36.   } 
  37. }  

ES6的新語法更加易懂。

注意:一定要在子類的構造方法裡呼叫super()方法。否則報錯。

呼叫super類內容


  1. class ES6DetectiveConan extends ES6Detective { 
  2.   constructor() { 
  3.     super(); 
  4.     console.log(`ES6DetectiveConan constructor`); 
  5.   } 
  6.  
  7.   solveCase(caseName) { 
  8.     super.solveCase(caseName); 
  9.  
  10.     if(!caseName) { 
  11.       console.log(`CONAN no case to solve`); 
  12.     } else { 
  13.       console.log(`CONAN case ` + caseName + ` is solved`); 
  14.     } 
  15.   } 
  16. }  

靜態方法可以被繼承

ES6的靜態方法可以被繼承。ES5的不可以。


  1. class ES6Detective { 
  2.   static countCases(place) { 
  3.     let p = !place ? `[maybe]` : place; 
  4.     console.log(`Counting cases…solve in ${p}`); 
  5.   } 
  6.  
  7. class ES6DetectiveConan extends ES6Detective { 
  8.   constructor() { 
  9.     super(); 
  10.     console.log(`ES6DetectiveConan constructor`); 
  11.   } 
  12.  
  13. // static method 
  14. ES6Detective.countCases(); 
  15. ES6DetectiveConan.countCases(`Japan`); 
  16.  
  17. // result 
  18. Counting cases…solve in [maybe] 
  19. Counting cases…solve in Japan  

在子類ES6DetectiveConan並沒有定義任何方法,包括靜態方法。但是,在父類和子類裡都可以呼叫該方法。

甚至,可以在子類裡呼叫父類的靜態方法:


  1. class ES6DetectiveConan extends ES6Detective { 
  2.   static countCases(place) { 
  3.     let p = !place ? `[maybe]` : place; 
  4.     super.countCases(p); 
  5.     console.log(`#Sub class:- Counting cases…solve in ${p}`); 
  6.   } 
  7.  
  8. // result 
  9. Counting cases…solve in [maybe] 
  10. Counting cases…solve in Japan 
  11. #Sub class:- Counting cases…solve in Japan  


作者:小紅星閃啊閃

來源:51CTO


相關文章