TypeScript访问修饰符 #
一、访问修饰符概述 #
1.1 什么是访问修饰符 #
访问修饰符用于控制类成员(属性和方法)的访问权限。TypeScript提供了四种访问修饰符:
public:公开访问(默认)private:私有访问protected:保护访问readonly:只读
1.2 修饰符对比 #
| 修饰符 | 类内部 | 子类 | 类外部 |
|---|---|---|---|
| public | ✓ | ✓ | ✓ |
| protected | ✓ | ✓ | ✗ |
| private | ✓ | ✗ | ✗ |
| readonly | 只读 | 只读 | 只读 |
二、public修饰符 #
2.1 默认修饰符 #
public是默认的访问修饰符,成员可以在任何地方访问。
typescript
class User {
public name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
const user = new User('Alice', 25);
console.log(user.name);
console.log(user.age);
2.2 显式声明 #
typescript
class User {
public name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public greet(): string {
return `Hello, I'm ${this.name}`;
}
}
2.3 参数属性 #
typescript
class User {
constructor(
public name: string,
public age: number
) {}
}
const user = new User('Alice', 25);
console.log(user.name);
三、private修饰符 #
3.1 基本用法 #
private成员只能在类内部访问。
typescript
class User {
private password: string;
constructor(password: string) {
this.password = password;
}
checkPassword(input: string): boolean {
return this.password === input;
}
}
const user = new User('secret');
console.log(user.password);
console.log(user.checkPassword('secret'));
3.2 封装数据 #
typescript
class BankAccount {
private balance: number = 0;
deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
}
}
withdraw(amount: number): boolean {
if (amount > 0 && this.balance >= amount) {
this.balance -= amount;
return true;
}
return false;
}
getBalance(): number {
return this.balance;
}
}
const account = new BankAccount();
account.deposit(100);
account.withdraw(50);
console.log(account.getBalance());
3.3 参数属性 #
typescript
class User {
constructor(
private password: string
) {}
checkPassword(input: string): boolean {
return this.password === input;
}
}
3.4 私有字段(ES2022) #
TypeScript支持JavaScript的私有字段语法#:
typescript
class User {
#password: string;
constructor(password: string) {
this.#password = password;
}
checkPassword(input: string): boolean {
return this.#password === input;
}
}
const user = new User('secret');
console.log(user.#password);
四、protected修饰符 #
4.1 基本用法 #
protected成员可以在类内部和子类中访问。
typescript
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
bark(): void {
console.log(`${this.name} barks!`);
}
}
const dog = new Dog('Max');
dog.bark();
console.log(dog.name);
4.2 共享基类功能 #
typescript
class Component {
protected element: HTMLElement;
constructor(container: HTMLElement) {
this.element = document.createElement('div');
container.appendChild(this.element);
}
protected render(): void {
this.element.innerHTML = '';
}
}
class Button extends Component {
private text: string;
constructor(container: HTMLElement, text: string) {
super(container);
this.text = text;
this.render();
}
protected render(): void {
super.render();
this.element.textContent = this.text;
}
}
4.3 参数属性 #
typescript
class Animal {
constructor(
protected name: string
) {}
}
class Dog extends Animal {
constructor(name: string, public breed: string) {
super(name);
}
showName(): void {
console.log(this.name);
}
}
五、readonly修饰符 #
5.1 基本用法 #
readonly修饰符使属性只读,只能在声明时或构造函数中赋值。
typescript
class User {
readonly id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
const user = new User(1, 'Alice');
user.id = 2;
user.name = 'Bob';
5.2 参数属性 #
typescript
class User {
constructor(
readonly id: number,
public name: string
) {}
}
const user = new User(1, 'Alice');
console.log(user.id);
user.id = 2;
5.3 只读数组 #
typescript
class Container {
readonly items: readonly number[];
constructor(items: number[]) {
this.items = items;
}
}
const container = new Container([1, 2, 3]);
container.items.push(4);
container.items = [4, 5, 6];
六、组合使用 #
6.1 多个修饰符组合 #
typescript
class User {
public readonly id: number;
private readonly secret: string;
protected readonly createdAt: Date;
constructor(
id: number,
secret: string
) {
this.id = id;
this.secret = secret;
this.createdAt = new Date();
}
}
6.2 getter/setter #
typescript
class User {
private _name: string = '';
get name(): string {
return this._name;
}
set name(value: string) {
if (value.length < 2) {
throw new Error('Name is too short');
}
this._name = value;
}
}
const user = new User();
user.name = 'Alice';
console.log(user.name);
6.3 私有setter #
typescript
class User {
private _age: number = 0;
get age(): number {
return this._age;
}
private set age(value: number) {
this._age = value;
}
setAge(value: number): void {
if (value >= 0) {
this.age = value;
}
}
}
七、访问修饰符与继承 #
7.1 继承中的访问控制 #
typescript
class Parent {
public publicProp: string = 'public';
protected protectedProp: string = 'protected';
private privateProp: string = 'private';
showAll(): void {
console.log(this.publicProp);
console.log(this.protectedProp);
console.log(this.privateProp);
}
}
class Child extends Parent {
showInherited(): void {
console.log(this.publicProp);
console.log(this.protectedProp);
console.log(this.privateProp);
}
}
7.2 重写时的访问控制 #
typescript
class Parent {
protected method(): void {
console.log('Parent method');
}
}
class Child extends Parent {
public method(): void {
console.log('Child method');
}
}
const child = new Child();
child.method();
7.3 不能降低可见性 #
typescript
class Parent {
public method(): void {}
}
class Child extends Parent {
private method(): void {}
}
八、实用示例 #
8.1 数据封装 #
typescript
class User {
private _password: string = '';
private _email: string = '';
get email(): string {
return this._email;
}
set email(value: string) {
if (this.validateEmail(value)) {
this._email = value;
}
}
setPassword(password: string): void {
if (this.validatePassword(password)) {
this._password = this.hashPassword(password);
}
}
checkPassword(password: string): boolean {
return this._password === this.hashPassword(password);
}
private validateEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
private validatePassword(password: string): boolean {
return password.length >= 8;
}
private hashPassword(password: string): string {
return password.split('').reverse().join('');
}
}
8.2 单例模式 #
typescript
class Singleton {
private static instance: Singleton;
private constructor() {}
static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
}
const instance = Singleton.getInstance();
8.3 构建器模式 #
typescript
class QueryBuilder {
private query: string = '';
public select(columns: string): this {
this.query += `SELECT ${columns} `;
return this;
}
public from(table: string): this {
this.query += `FROM ${table} `;
return this;
}
public where(condition: string): this {
this.query += `WHERE ${condition} `;
return this;
}
public build(): string {
return this.query.trim();
}
}
九、最佳实践 #
9.1 最小权限原则 #
typescript
class User {
private password: string;
protected createdAt: Date;
public name: string;
constructor(name: string, password: string) {
this.name = name;
this.password = password;
this.createdAt = new Date();
}
}
9.2 使用getter/setter #
typescript
class User {
private _age: number = 0;
get age(): number {
return this._age;
}
set age(value: number) {
if (value >= 0 && value <= 150) {
this._age = value;
}
}
}
9.3 使用readonly保护不可变数据 #
typescript
class Configuration {
readonly apiUrl: string;
readonly apiKey: string;
constructor() {
this.apiUrl = process.env.API_URL!;
this.apiKey = process.env.API_KEY!;
}
}
十、总结 #
本章介绍了TypeScript的访问修饰符:
修饰符类型 #
- public:公开访问(默认)
- private:私有访问,仅类内部
- protected:保护访问,类内部和子类
- readonly:只读属性
最佳实践 #
- 遵循最小权限原则
- 使用getter/setter封装数据
- 使用readonly保护不可变数据
- 合理组合使用多个修饰符
最后更新:2026-03-26