TS中private protected public readonly的区别

在TypeScript中,privateprotectedpublicreadonly是用于类成员(属性和方法)访问控制和可变性的关键字。以下是它们各自的作用和区别:

Public

  • public是默认的访问修饰符,如果未指定,则成员默认为public
  • public成员可以在类的外部被访问和修改。
    class Person {
      public name: string; // public是默认的,所以可以省略public关键字
    
      constructor(name: string) {
        this.name = name;
      }
    
      public getName(): string {
        return this.name;
      }
    }
    
    const person = new Person('Alice');
    console.log(person.name); // 可以访问
    person.name = 'Bob'; // 可以修改
    

    Private

  • private成员只能在类内部被访问和修改,不能在类的外部被访问,即使是子类也不能访问。
  • 子类不能覆盖private成员。
    class Person {
      private name: string;
    
      constructor(name: string) {
        this.name = name;
      }
    
      public getName(): string {
        return this.name;
      }
    }
    
    const person = new Person('Alice');
    // console.log(person.name); // 错误:属性“name”为私有属性,只能在类“Person”中访问。
    

    Protected

  • protected成员可以在类内部和继承该类的子类中被访问和修改。
  • 子类可以覆盖protected成员。
    class Person {
      protected name: string;
    
      constructor(name: string) {
        this.name = name;
      }
    
      public getName(): string {
        return this.name;
      }
    }
    
    class Employee extends Person {
      constructor(name: string, public title: string) {
        super(name);
      }
    
      public getDetails(): string {
        return `${this.name},${this.title}`; // 可以访问protected成员
      }
    }
    
    const employee = new Employee('Alice', 'Developer');
    // console.log(employee.name); // 错误:属性“name”为受保护的属性,只能在类“Person”及其子类中访问。
    

    Readonly

  • readonly关键字用于属性,表示该属性只能在构造函数中被赋值,之后就不能再被修改。
  • readonly属性可以是publicprotectedprivate
    class Person {
      readonly name: string;
    
      constructor(name: string) {
        this.name = name;
      }
    }
    
    const person = new Person('Alice');
    console.log(person.name); // 可以访问
    // person.name = 'Bob'; // 错误:无法分配到“name”,因为它是只读属性。
    

<think>好的,用户现在问的是TypeScript中的constructor关键字。我需要先回顾一下之前的历史对话,看看用户之前问过什么问题,从而更好地理解他们的知识水平和需求。 之前用户问过关于TS中let关键字的问题,我详细解释了let的作用域、变量重新声明、类型标注、暂时性死区以及编译结果。用户可能现在在学习TypeScript的基础,特别是关于类和相关概念。constructor是类中的一个重要部分,所以用户可能在尝试理解如何创建和使用类,或者遇到相关的代码示例需要解释。 接下来,我需要确定用户的具体需求。他们可能想了解constructor的基本用法,如何初始化对象,或者与JavaScript中的constructor有什么区别。另外,用户可能对TypeScript特有的功能,如参数属性修饰符(publicprivate等)感兴趣,或者在使用constructor时遇到问题,比如类型检查或继承相关的问题。 我需要确保回答覆盖以下几个方面: 1. constructor的基本定义和作用。 2. 在TypeScript中constructor与JavaScript区别,特别是参数属性和访问修饰符。 3. 构造函数的类型标注和重载。 4. 继承中的super调用。 5. 与普通函数的区别。 6. 实际使用场景的例子。 另外,用户可能需要一些示例代码来更好地理解这些概念。之前回答let的时候用了代码示例,这次也应该保持一致性,提供清晰的例子。 还需要注意用户可能的误区,比如在JavaScript中,构造函数可以不用class语法,但在TypeScript中通常使用class。同时,TypeScript的constructor参数属性可能对新手来说比较陌生,需要详细解释。 检查是否有其他需要注意的点,比如编译后的代码是怎样的,或者与接口、泛型的结合使用,但考虑到用户当前的问题可能更基础,暂时不需要深入这些高级主题,但可以简要提及。 最后,确保回答结构清晰,逐步解释,帮助用户逐步理解constructor关键字在TypeScript中的使用和特点。</think>在 TypeScript 中,`constructor` 关键字是用于定义**类构造函数**的特殊方法。以下是逐步解析: --- ### 1. **核心作用** - **对象初始化**:当通过 `new` 创建类实例时自动调用 - **属性赋值**:主要用于初始化类成员变量 - **参数接收**:允许传递初始值给类的实例 基础示例: ```typescript class Person { name: string; age: number; // 构造函数 constructor(name: string, age: number) { this.name = name; this.age = age; } } const alice = new Person("Alice", 30); // 触发构造函数 ``` --- ### 2. **TypeScript 特有功能** #### ▸ **参数属性修饰符** (Parameter Properties) - 直接在构造函数参数中声明类属性 - 支持 `public`/`private`/`protected`/`readonly` 修饰符 简化写法: ```typescript class Student { // 等价于声明属性 + 自动赋值 constructor( public id: number, private course: string ) {} } const stu = new Student(1001, "Math"); console.log(stu.id); // 1001(public可访问) console.log(stu.course); // 报错(private不可访问) ``` --- ### 3. **类型标注与重载** #### ▸ **构造函数类型** - 通过 `new` 关键字定义构造签名 ```typescript interface AnimalConstructor { new (name: string): Animal; } class Animal { constructor(public name: string) {} } function createAnimal(ctor: AnimalConstructor, name: string) { return new ctor(name); } ``` #### ▸ **构造函数重载** - 支持通过不同参数组合初始化对象 ```typescript class Vector { x: number; y: number; // 重载声明 constructor(); constructor(x: number, y: number); // 实现签名 constructor(x?: number, y?: number) { this.x = x ?? 0; this.y = y ?? 0; } } const v1 = new Vector(); // (0,0) const v2 = new Vector(3,4); // (3,4) ``` --- ### 4. **继承中的 super()** - 派生类必须通过 `super()` 调用父类构造函数 - 必须在访问 `this` 之前调用 继承示例: ```typescript class Employee extends Person { department: string; constructor(name: string, age: number, department: string) { super(name, age); // 必须首先调用 this.department = department; } } ``` --- ### 5. **与普通函数的区别** | 特性 | 构造函数 | 普通函数 | |---------------------|---------------------------|--------------------------| | 调用方式 | 必须通过 `new` 调用 | 直接调用 | | 返回值 | 隐式返回实例对象 | 可返回任意值 | | `this` 指向 | 指向新创建的实例 | 严格模式为 `undefined` | | 原型链 | 自动关联 `prototype` | 无自动关联 | --- ### 6. **典型使用场景** - 初始化对象状态 - 依赖注入(通过参数传递外部资源) - 实现工厂模式 - 构建不可变对象(配合 `readonly`) ```typescript class ImmutablePoint { constructor( public readonly x: number, public readonly y: number ) {} } const p = new ImmutablePoint(5, 5); p.x = 10; // 编译错误:readonly属性 ``` --- ### 编译结果观察 当编译为 ES6 时: ```javascript class Person { constructor(name, age) { this.name = name; this.age = age; } } ``` 当编译为 ES5 时: ```javascript var Person = /** @class */ (function () { function Person(name, age) { this.name = name; this.age = age; } return Person; }()); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值