傳統的 JavaScript 程式使用函式和基於原型的繼承來建立可重用的元件,從 ES6 開始,JavaScript 程式能夠使用基於類的物件導向的方式。使用 TypeScript,你可以使用 ES6 中規定的新特性,編譯後的 JavaScript 可以在所有主流瀏覽器和平臺上執行。
基本用法
class Person {
public love: string;
constructor(love: string) {
this.love = love;
}
public sayLove() {
console.log(`my love is ${this.love}`)
}
}
複製程式碼
繼承
在構造器裡訪問 this 的屬性之前,一定要呼叫 super() ,這個是 TypeScript 強制執行的一條重要規則。
class Person {
public love: string;
constructor(love: string) {
this.love = love;
}
public sayLove() {
console.log(`my love is ${this.love}`)
}
}
class SuperPerson extends Person {
public name: string;
constructor(love: string, name: string) {
super(love);
this.name = name;
}
public sayName(){
console.log(`my name is ${this.name}`)
}
}
let me = new SuperPerson('HTML', 'funlee');
me.sayLove()
me.sayName()
複製程式碼
訪問控制
public、private、protected
預設是 public, 不再贅述,參考前面例子。
當成員標記為 private 時,它就不能在宣告它的類的外部訪問,用 protected 修飾的屬性依然如此。
class Person {
private love: string; // or prot
constructor(love: string) {
this.love = love;
}
public sayLove() {
console.log(`my love is ${this.love}`)
}
}
let me = new Person('TS');
me.love = 'JS'; // error
複製程式碼
private 和 protected 有一點不同, protected 成員在派生類中仍然可以訪問。例如:
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Man extends Person {
private love: string;
constructor(name: string, love: string) {
super(name);
this.love = love;
}
public say() {
// 如果Person 中用 private 修飾 name 則不能訪問到 name 屬性
console.log(`my name is ${this.name}, and my love is ${this.love}`);
}
}
let me = new Man('funlee', 'TS');
複製程式碼
注意:TypeScript 使用的是結構性型別系統,所以當比較兩種不同的型別時,如果所有的成員的型別都是相容的,那麼這兩個型別就是相容的。如:
class A {
prop1: string
}
class B {
prop1: string
prop2: string
}
let instance:A = new B() // 允許這麼做,因為A的所有成員型別,B中都有
複製程式碼
但是如果被比較的類裡面含有 private 和 protected 型別成員的時候,情況就不同了,這時候需要另一個類裡也含有相應的 private 或 protected 成員,型別才能是相容的,所以有:
class A {
private prop1: string
}
class B {
private prop2: string
}
let p1:A = new B() // 報錯
class C extends A {
}
let p2:A = new C() // 允許這麼做
複製程式碼
readonly
可以使用 readonly 關鍵字將屬性設定為只讀的,只讀屬性必須在宣告時或建構函式裡被初始化。
class Person {
readonly name: string;
constructor(name: string) {
this.name = name;
}
}
let me = new Person('funlee');
me.name = 'new name'; // error
複製程式碼
引數屬性
引數屬性允許同時建立和初始化成員,可以把宣告和賦值合併至一處,如:
class Person {
constructor(public name: string, protected love: string, readonly age: number, private weight: string) {
this.name = name;
this.love = love;
this.age = age;
}
public sayWeight() {
console.log(`my weight is ${this.weight}`)
}
}
let me = new Person('funlee', 'TS', 18, '55kg');
me.sayWeight()
複製程式碼
存取器
TypeScript 支援 getter 和 setter,但是有一點限制:編譯器輸出必須設為 ES5 或者更高,不支援降級到 ES3,另外,當一個存取器只帶有 get 卻不帶有 set 時,它會被自動推斷為 readonly。
class Person {
public _love: string;
constructor(love: string) {
this._love = love;
}
get love(): string{
return this._love;
}
set love(newLove: string) {
this._love = `error!! my love can't be chenged`;
}
}
let me = new Person('TS');
console.log(me.love); // TS
me.love = 'HTML';
console.log(me.love); // error!! my love can't be chenged
複製程式碼
靜態屬性
可以使用static來定義類裡的靜態屬性,靜態屬性屬於類自身,而不屬於例項,訪問的時候要用類名訪問,而不能用例項物件訪問,如:
class Person {
static love: string = 'TS';
}
let me = new Person();
console.log(Person.love); // TS
console.log(me.love); // error
複製程式碼
抽象類
抽象類只能作為其他派生類的基類使用,抽象類不能被例項化,它具有如下特點:
- 抽象類可以包含成員的實現細節,且抽象類必須用 abstract 宣告
- 抽象類裡不含方法體的方法稱為抽象方法,使用 abstract 宣告,抽象方法必須被子類實現(抽象方法必須使用 abstract 關鍵字宣告,且可以包含訪問修飾符)
abstract class Person {
public love: string;
constructor(love: string) {
this.love = love;
}
abstract sayLove(): string; // 必須在派生類中實現
}
class Man extends Person{
constructor(love: string){
super(love)
}
sayLove() {
return `my love is ${this.love}`;
}
}
let me = new Man('TS');
console.log(me.sayLove()); // my love is TS
複製程式碼
把類當做介面使用
類定義會建立兩個東西:類的例項型別和一個建構函式,因為類可以建立出型別,所以能夠在允許使用介面的地方使用類。
class Person {
name: string;
age: number;
}
interface Man extends Person {
love: string;
}
let me: Man = {
name: 'funlee',
age: 18,
love: 'TS'
}
複製程式碼