無論React還是RN都已經(jīng)邁入了ES6的時(shí)代萝毛,甚至憑借Babel的支持都進(jìn)入了ES7楷力。ES6內(nèi)容很多眉厨,本文主要講解類相關(guān)的內(nèi)容锌奴。
構(gòu)造函數(shù)
定義偵探類作為例子。
ES5的“類”是如何定義的憾股。
function ES5Detective() {
console.log('##ES5Detective contructor');
}
ES6定義類:
class ES6Detective {
constructor() {
console.log('Detective constructor');
}
}
ES6使用了class關(guān)鍵字鹿蜀,而且有專門的constructor。ES5里的function ES5Detective
既是類的定義服球,也是構(gòu)造函數(shù)茴恰。
屬性
看看這個(gè)偵探是從哪本書出來的。
ES5:
ES5Detective.prototype.fromBookName = 'who';
ES6:
class ES6Detective {
detectiveName: string;
_bookName: string;
constructor() {
console.log('Detective constructor');
this.detectiveName = 'Detective who'; // 屬性
}
}
ES6 getter & setter
class ES6Detective {
detectiveName: string;
_bookName: string;
constructor() {
console.log('Detective constructor');
this.detectiveName = 'Detective who';
this._bookName = 'who';
}
get fromBookName() {
return this._bookName;
}
set fromBookName(value) {
this._bookName = value;
}
}
如果只有g(shù)etter沒有setter而賦值的話就會(huì)出現(xiàn)下面的錯(cuò)誤:
detective.bookAuthor = 'A C';
^
TypeError: Cannot set property bookAuthor of #<ES6Detective> which has only a getter
實(shí)例方法
偵探是如何解決案件的有咨。
ES5:
ES5Detective.prototype.solveCase = function(caseName) {
var dn = this.dectiveName;
if(!caseName) {
console.log('SOLVE CASE: ' + dn + ' no case to solve');
} else {
console.log('SOLVE CASE: ' + dn + ' get case ' + caseName + ' is solved');
}
};
或者:
function ES5Detective() {
this.dectiveName = 'Detective who';
console.log('##ES5Detective contructor');
// 實(shí)例方法
this.investigate = function(scene) {
console.log('investigate ' + scene);
}
this.assistant = "assistant who";
}
ES6:
class ES6Detective {
detectiveName: string;
_bookName: string;
constructor() {
console.log('Detective constructor');
this.detectiveName = 'Detective who';
this._bookName = 'who';
}
solveCase(caseName) {
if(!caseName) {
console.log('no case to solve');
} else {
console.log('case ' + caseName + ' is solved');
}
}
}
ES6添加方法非常簡單直接琐簇。ES5中添加實(shí)例方法有兩種方法,一是在prototype里定義座享,一是在構(gòu)造函數(shù)重定義婉商。在構(gòu)造函數(shù)中定義的實(shí)例方法和屬性在每一個(gè)實(shí)例中都會(huì)保留一份,而在原型中定義的實(shí)例方法和屬性是全部實(shí)例只有一份渣叛。
另外丈秩,在ES5的構(gòu)造函數(shù)重定義的實(shí)例方法可以訪問類的私有變量。比如:
function ES5Detective() {
console.log('##ES5Detective contructor');
var available: boolean = true; // private field. default income is ZERO.
this.investigate = function(scene) {
if (available) {
console.log('investigate ' + scene);
} else {
console.log(`i'm not available`);
}
}
}
在其他的方法訪問的時(shí)候就會(huì)報(bào)錯(cuò)淳衙。
if (!available) {
^
靜態(tài)方法
ES5:
ES5Detective.countCases = function(count) {
if(!count) {
console.log('no case solved');
} else {
console.log(`${count} cases are solved`);
}
};
類名后直接定義方法蘑秽,這個(gè)方法就是靜態(tài)方法。
ES5Detective.countCases();
ES6:
class ES6Detective {
static countCases() {
console.log(`Counting cases...`);
}
}
// call it
ES6Detective.countCases();
繼承
ES6使用extends關(guān)鍵字實(shí)現(xiàn)繼承箫攀。
ES5:
function ES5Detective() {
var available: boolean = true; // private field.
this.dectiveName = 'Detective who';
console.log('##ES5Detective contructor');
this.investigate = function(scene) {
// 略
}
this.assistant = "assistant who";
}
ES5Detective.prototype.solveCase = function(caseName) {
// 略
}
// inheritance
function ES5DetectiveConan() {
// first line in constructor method is a must!!!
ES5Detective.call(this);
this.dectiveName = 'Conan';
}
// inheritance
ES5DetectiveConan.prototype = Object.create(ES5Detective.prototype);
ES5DetectiveConan.prototype.constructor = ES5DetectiveConan;
ES5繼承的時(shí)候需要注意兩個(gè)地方:
- 需要在子類的構(gòu)造函數(shù)里調(diào)用
SuperClass.call(this[, arg1, arg2, ...])
- 子類的prototype賦值為:
SubClass.prototype = Object.create(SuperClass.prototype)
肠牲,然后把構(gòu)造函數(shù)重新指向自己的:SubClass.prototpye.constructor = SubClass
。
ES6:
class ES6Detective {
constructor() {
console.log('Detective constructor');
this.detectiveName = 'Detective who';
this._bookName = 'who';
}
solveCase(caseName) {
if(!caseName) {
console.log('no case to solve');
} else {
console.log('case ' + caseName + ' is solved');
}
}
get fromBookName() {
return this._bookName;
}
set fromBookName(value) {
this._bookName = value;
}
get bookAuthor() {
return 'Author Who';
}
static countCases() {
console.log(`Counting cases...`);
}
}
class ES6DetectiveConan extends ES6Detective {
constructor() {
super();
console.log('ES6DetectiveConan constructor');
}
}
ES6的新語法更加易懂靴跛。
注意:一定要在子類的構(gòu)造方法里調(diào)用super()
方法缀雳。否則報(bào)錯(cuò)。
調(diào)用super類內(nèi)容
class ES6DetectiveConan extends ES6Detective {
constructor() {
super();
console.log('ES6DetectiveConan constructor');
}
solveCase(caseName) {
super.solveCase(caseName);
if(!caseName) {
console.log('CONAN no case to solve');
} else {
console.log('CONAN case ' + caseName + ' is solved');
}
}
}
靜態(tài)方法可以被繼承
ES6的靜態(tài)方法可以被繼承梢睛。ES5的不可以肥印。
class ES6Detective {
static countCases(place) {
let p = !place ? '[maybe]' : place;
console.log(`Counting cases...solve in ${p}`);
}
}
class ES6DetectiveConan extends ES6Detective {
constructor() {
super();
console.log('ES6DetectiveConan constructor');
}
}
// static method
ES6Detective.countCases();
ES6DetectiveConan.countCases('Japan');
// result
Counting cases...solve in [maybe]
Counting cases...solve in Japan
在子類ES6DetectiveConan
并沒有定義任何方法,包括靜態(tài)方法绝葡。但是深碱,在父類和子類里都可以調(diào)用該方法。
甚至藏畅,可以在子類里調(diào)用父類的靜態(tài)方法:
class ES6DetectiveConan extends ES6Detective {
static countCases(place) {
let p = !place ? '[maybe]' : place;
super.countCases(p);
console.log(`#Sub class:- Counting cases...solve in ${p}`);
}
}
// result
Counting cases...solve in [maybe]
Counting cases...solve in Japan
#Sub class:- Counting cases...solve in Japan
代碼
https://github.com/future-challenger/ES-Samples/tree/master/class