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的访问修饰符:

修饰符类型 #

  1. public:公开访问(默认)
  2. private:私有访问,仅类内部
  3. protected:保护访问,类内部和子类
  4. readonly:只读属性

最佳实践 #

  1. 遵循最小权限原则
  2. 使用getter/setter封装数据
  3. 使用readonly保护不可变数据
  4. 合理组合使用多个修饰符
最后更新:2026-03-26