TypeScript 中的 class 可以為屬性加上 5 種前綴來決定存取該屬性的權限 — public ( default ), private, static, protected, readonly,簡單筆記一下 5 種前綴的存取權。
Table of Contents
1. Public
- 如果沒有在屬性前加上任何前綴,那麼 TypeScript 會預設這個屬性是 public 。
- 要存取 class 裡的屬性,請先記得 new 一個 instance ,否則就算將屬性設置為 public ,也無法直接從 class 存取到屬性。
class Property {
public firstName: string;
height: number;
constructor() {
this.firstName = 'Jimmy';
this.height = 180
}
}
const propertyInstance = new Property();
console.log(Property.firstName);
// Property 'firstName' does not exist on type 'typeof Property'.
console.log(propertyInstance.name);
// 'Jimmy'
console.log(Property.height);
// Property 'height' does not exist on type 'typeof Property'.
console.log(propertyInstance.height);
// 180
2. Private
- private 是 TypeScript 提供的屬性前綴,要在 JavaScript 中產生類似的效果,只要在屬性名稱前加上’#’即可,ex: #_name。
- private 代表屬性是 class 私有的,只有在 class 內部才存取的到,從外部直接存取 class 本體的 private 屬性,或是 new 一個 instance 存取 private 屬性都會有 error。
- 要從外部存取 private 屬性的方法只能寫一個 getter 或是 function 來回傳內部的 private 屬性。要注意的是 getter 只能 new instance 後呼叫,不能直接從 class 本體呼叫。
class Property {
// 一般來說習慣將 private 的屬性加上_,標示為 private
private _age: number;
constructor() {
this._age = 18;
}
get get_age() {
return this._age;
}
}
const propertyInstance = new Property();
console.log(Property._age);
// Error!! Property '_age' is private and only accessible within class 'Property'.
console.log(propertyInstance._age);
// Error!! Property '_age' is private and only accessible within class 'Property'.
console.log(Property.get_age)
// Error!! Property 'get_age' does not exist on type 'typeof Property'.
console.log(propertyInstance.get_age);
// 18
3. Protected
- 在屬性前面加上 protected 後只有 class 內部和繼承該 class 的 子class 可以存取的到該屬性。
- 在 子class 內部可以直接用 this.[屬性] 存取到 父class 的 protected 屬性。
- protected 屬性無法在外部直接從 class 本體或是 instance 存取。
class Property {
protected address: string;
constructor() {
this.address = 'Taipei';
}
}
class PropertyChild extends Property {
getAddress() {
return this.address;
}
}
const propertyInstance = new Property();
const propertyChild = new PropertyChild();
console.log(Property.address);
// Error!! Property 'address' does not exist on type 'typeof Property'.
console.log(propertyInstance.address);
// Error!! Property 'address' is protected and only accessible within class 'Property' and its subclasses.
console.log(PropertyChild.address);
// Error!! Property 'address' does not exist on type 'typeof Property'.
console.log(propertyChild.address);
// Error!! Property 'address' is protected and only accessible within class 'Property' and its subclasses.
console.log(propertyChild.getAddress());
// 'Taipei'
4. Static
- 加上 static 的屬性只能直接從 class 本體存取,不能 new instance 後再用 instance 存取。
- 加上 static 的屬性在 class 內部要使用的話要用 [class name].[static 屬性]來存取,而不是 public 或 private 的 this.[屬性] 。
- 加上 static 的 function 一樣只能直接用 class 本體存取。
class Property {
static age: number;
constructor() {
Property.age = 18;
}
static staticFunction() {
return 'staticFunction works!!'
};
}
const propertyInstance = new Property();
console.log(Property.age);
// 18
console.log(propertyInstance.age);
// Error!! Property 'age' does not exist on type 'Property'.
console.log(Property.staticFunction());
// 'staticFunction works!!'
console.log(propertyInstance.staticFunction);
// Error!! Property 'staticFunction' does not exist on type 'Property'.
5. ReadOnly
- readonly 的屬性只能存取不能修改。
- readonly 也可以用在 interface 中。
// 用在 class
class Employee {
readonly empCode: number;
empName: string;
constructor(code: number, name: string) {
this.empCode = code;
this.empName = name;
}
}
const employee = new Employee(101, 'Jimmy');
employee.empCode = 102;
// Error!! Cannot assign to 'empCode' because it is a read-only property.
// 用在 interface
interface IEmployee {
empCode: number;
empName: string;
}
let emp1: Readonly<IEmployee> = {
empCode:1,
empName:"Steve"
}
emp1.empCode = 100;
// Compiler Error: Cannot assign to 'empCode' because it is a read-only property.
emp1.empName = 'Bill';
// Compiler Error: Cannot assign to 'empCode' because it is a read-only property.
let emp2: IEmployee = {
empCode:1,
empName:"Steve"
}
emp2.empCode = 100; // OK
emp2.empName = 'Bill'; // OK
6. 參考資料
TypeScript Data Modifiers: public, private, protected, static, readonly