在ES5中,只有對象的概念,對象是經過構造函數建立出來的,構造函數自己也是對象。因此說JavaScript是一種基於對象的語言。程序員
ES6以後,有了class,也就是咱們的類,雖然class實質上是 JavaScript 現有的基於原型的繼承的語法糖。但咱們一樣能夠借鑑C#語言的面向對象的思想去理解它。讓咱們夠使用==基於類的面向對象的方式==。編程
類就是對象的設計圖紙,上面記錄着一個事物應該有哪些字段,哪些方法,但類不是個對象,只是對象的定義。經過new 一個類,咱們才能獲得一個對象,這個對象有類上描述的全部成員。bash
這就是基於類的面向對象的方式。程序員畫好了許許多多的設計圖(類)。而後new 它們,造成了一個一個的對象,對象之間彼此關聯,協做。咱們的程序就這樣運行了。函數
因此咱們有了類的概念,通曉類與對象的關係後,這會影響咱們的編程思惟方式,須要什麼東西,先定義個類,在new出個對象,讓其工做。咱們的對象更加具象了,它有類給予它的定義。學習
下面咱們就來認識TypeScript中的類ui
class Person {
}
複製代碼
類內的成員有:字段、存取器、構造函數、方法。this
class Person {
age: number; // 這就是一個字段
}
複製代碼
類中的變量成員。能夠被實例化的對象設置和讀取。也能夠被類內其餘成員設置和讀取。spa
class Person {
private _age: number;
get age(): number {
return this._age;
}
set age(newName: number) {
if(newName > 150){
this._age = 150;
}
this._age = newAge;
}
}
複製代碼
這裏的get/set方法,就是_age變量的存取器。首先咱們爲_age變量添加一個private修飾符。表示它是個私有變量,禁止外部對它的訪問。設計
const person = new Person();
person._age // 這句會報錯,TS不容許咱們讀取私有變量。
複製代碼
要想使用_age,須要利用存取器:code
const person = new Person();
person.age = 15; // 使用set age方法
const age = pereson.age; // 使用get age方法
複製代碼
使用存取器的好處是對變量的訪問和設置,有了控制。原則上類內部的變量,外部是不能訪問的,這就是封裝性。要想訪問,只能經過存取器方法。
class Person {
private _age: number;
constructor(age: number) {
this._age = age;
}
}
複製代碼
constructor就是類的構造器,他的使用以下:
const person = new Person(15);
複製代碼
構造器就是咱們在new一個類的時候,調用的方法。
JavaScript中,都叫函數,可是有了類以後,類中的函數成員,就叫方法。
class Person {
eat() {
....
}
drink() {
}
}
複製代碼
這裏的eat和drink,就是Person類的方法。
和原生js中捉摸不定的this不一樣,類中的this,很是好理解,它表示當前類的實例。
繼承,本質上講是一種代碼重用機制。 類的繼承是指一個類繼承另外一個類,那麼這個類的實例上,也會有被繼承類的屬性和方法。
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
複製代碼
extends關鍵字就是指Dog類繼承自Animal類。 Animal叫作父類。Dog叫作子類。
說到類的繼承,一樣帶來了一些問題,須要咱們瞭解一下。
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
move(distanceInMeters: number = 0) {
console.log(`Dog moved ${distanceInMeters}m.`);
}
bark() {
console.log('Woof! Woof!');
}
}
const dog: Animal = new Dog();
dog.move(10); // Dog moved 10
複製代碼
Dog類對Animal的move類進行了重寫,調用Dog實例的move方法時,會調用Dog類重寫的move方法。
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
}
class Dog extends Animal {
constructor(name: string) { super(name); }
}
複製代碼
若是子類想使用父類中構造函數的邏輯,在子類的構造函數中,super()就是指父類構造函數。
TypeScript還爲咱們提供了類成員的訪問修飾符。public,private,protected。表明了成員的三個不一樣的訪問級別。
使用方式:
class Person {
private name: string;
protected age: string;
public height: string;
}
const john = new Person("John");
john.name; // 報錯
jonh.age; // 報錯
jonh.height; // 正確
複製代碼
上面看到private和protected在類的外部,都不能夠訪問,public的能夠。那麼private和protected有什麼區別呢?
class Employee extends Person {
getInfo() {
this.name; // 報錯
this.age; // 正確
}
}
複製代碼
區別就在於在繼承類中,protected的成員,仍然能夠被訪問到,可是private的不行。
可使用readonly關鍵字將屬性設置成功只讀,至關於類字段的const。
class Person {
readonly name: string = 'john'; // 我只讀
constructor(theName: string) {
this.name = theName; // 能夠
}
setName() {
this.name = 'lili'; // 報錯
}
}
複製代碼
只能在初始化和構造函數中賦值,其餘地方不容許賦值。
類中的成員還能夠用static關鍵字來修飾,那麼它就成了全部實例共有的成員。
class Person {
static globalPeopleCount: number = '7000000000';
}
const john = new Person();
john.globalPeopleCount += 1;
const lili = new Person();
lili.globalPeopleCount // 7000000001
複製代碼
抽象類是一種不能被實例化的類,它的目的就是用來繼承的,抽象類裏面能夠有抽象的成員,就是本身不實現,等着子類去實現。
抽象類和抽象成員,都是用abstract修飾:
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('roaming the earch...');
}
}
複製代碼
抽象類中仍是能夠有具體實現的,這樣子類若是不實現,能夠繼承抽象類中的實現。
學習TS中的類,理解基於類的面向對象思惟,能夠幫助咱們更好的應用面向對象思惟,去解決項目的問題。