TypeScript 基礎入門-Class

前言

類別(class)這個是在 ES6 引入的,而這個功能又有何用處呢?讓我們來研究一下

類別(class)

在準備講 TypeScript 的 Class 之前必須先知道原本 JavaScript 其實是不支援 Class 的,由於早期我們如果要建構新的物件的時候,是必須這樣子撰寫的

1
2
3
4
5
6
7
8
9
10
userName.prototype.sayHi = function () {
console.log(`Hello ${this.name}`);
}

function userName(name) {
this.name = name;
}

const user = new userName('Jack');
user.sayHi();

prototype

ES6 引入之後寫法就有點稍微不同了,首先裡面會有兩個主要方法

  • constructor 建構子方法
  • other 方法

讓我們從範例來略知一二

1
2
3
4
5
6
7
8
9
10
class userName {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(`Hello ${this.name}`);
}
}
const user = new userName('Jack');
user.sayHi();

class

但是這邊要知道一件事情 ES6 的 Class 只一個語法糖(就是方便你而已),並不是真的要取代原本的 prototype 的做法。

TypeScript Class 寫法

而 TypeScript Class 的寫法是這樣子

1
2
3
4
5
6
7
8
9
10
11
class userName {
name: string; // 會對應到底下的 this.name
constructor(name: string) {
this.name = name;
}
sayHi() {
console.log(`Hello ${this.name}`);
}
}
const user = new userName('Jack');
user.sayHi();

另外 TypeScript 還可以特定三個訪問屬性,分別為以下

  • public
  • 預設在這底下所有的屬性與方法都是 public
  • private
  • 使用這個屬性的方法與屬性都是 private,不能在它聲明之外的地方使用
  • protected
  • private 有點像,但是它是可以被子類別所取用

讓我們一個一個來撰寫了解吧

public

(預設不寫都會是 public)

1
2
3
4
5
6
7
8
9
10
11
12
13
class userName {
public name: string;
public constructor(name: string) {
this.name = name;
}
public sayHi() {
console.log(`Hello ${this.name}`);
}
}
const user = new userName('Jack');
user.sayHi(); // Hello Jack
user.name = 'Tom'; // 通過原型來修改傳入的 name
user.sayHi(); // Hello Tom

private
但是當如果我們必須要 name 被其他人修改呢?那就使用 private

1
2
3
4
5
6
7
8
9
10
11
12
13
class userName {
private name: string;
public constructor(name) {
this.name = name;
}
public sayHi() {
console.log(`Hello ${this.name}`);
}
}
const user = new userName('Jack');
user.sayHi(); // Hello Jack
user.name = 'Tom';
user.sayHi();

這樣我們就會的到一個錯誤

private

而且就算繼承下來也是無法使用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class userName {
private name: string;
public constructor(name) {
this.name = name;
}
public sayHi() {
console.log(`Hello ${this.name}`);
}
}
class boy extends userName {
constructor(name) {
super(name); // 使用 super 來取得父類 (userName) 的 name 屬性
console.log(this.name);
}
}
const user = new userName('Jack');
user.sayHi(); // Hello Jack
user.name = 'Tom';
user.sayHi();

這樣子也是會得到一個錯誤

private

protected

protected 呢?一般使用情況下 protectedprivate 看不出差異

1
2
3
4
5
6
7
8
9
10
11
12
13
class userName {
protected name: string;
public constructor(name) {
this.name = name;
}
public sayHi() {
console.log(`Hello ${this.name}`);
}
}
const user = new userName('Jack');
user.sayHi(); // Hello Jack
user.name = 'Tom';
user.sayHi();

但是最大差異在於繼承,protected 允許你去取用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class userName {
protected name: string;
public constructor(name) {
this.name = name;
}
public sayHi() {
console.log(`Hello ${this.name}`);
}
}
class boy extends userName {
constructor(name) {
super(name); // 使用 super 來取得父類 (userName) 的 name 屬性
console.log(this.name);
}
}
const user = new userName('Jack');
user.sayHi(); // Hello Jack
user.name = 'Tom';
user.sayHi();

protected

最後補充關於 Class 的觀念

感謝友站宇軒大大用遊戲的方式來舉例給我了解,以下來自它的解釋

1
2
3
4
5
6
7
8
9
10
11
prototype 原型 我會想用遊戲的方式來比喻

像是用 RO 來說的話
初心者就好像是所有職業的原型
不管你之後的一轉、二轉、三轉、進階二轉

全部都是繼承初心者的

也就是說初心者的技能(方法)大家都會,

因此你如果是盧恩騎士,你仍然可以使用緊急治療 (從初心者那裏繼承來的方法,盧恩騎士本身不會,所以當盧恩騎士使用時,是從盧恩騎士>騎士領主>騎士>劍士>初心者) 這樣子慢慢往回找有沒有緊急治療這個技能 (方法)

在這上面充分的使用的原型、原型鏈及原型繼承的概念,是比較容易懂這個 prototype 的概念。

可以給點牡蠣。
Google AD