Skip to content

存取器属性 (Accessor Properties)

存取器属性是 TypeScript 和 JavaScript 中用于定义对象属性的一种特殊方式,它允许你通过 getter 和 setter 方法来控制对属性的访问和修改。这种方式不仅增强了代码的封装性,还提供了在读取或设置属性值时执行额外逻辑的能力。

1. 基本概念

存取器属性由一对可选的方法组成:getsetget 方法用于定义属性的读取行为,而 set 方法用于定义属性的写入行为。你可以单独定义 getset 方法,也可以同时定义两者。

  • get:当读取属性值时调用。
  • set:当设置属性值时调用。

2. 语法

typescript
class MyClass {
  private _value: number;

  constructor(value: number) {
    this._value = value;
  }

  get value(): number {
    return this._value;
  }

  set value(newValue: number) {
    if (newValue >= 0) {
      this._value = newValue;
    } else {
      console.log("Value must be non-negative.");
    }
  }
}

在这个例子中,value 是一个存取器属性,它使用了 getset 方法来控制对 _value 私有属性的访问。

3. 示例解析

示例 1: 基本存取器

typescript
class Circle {
  private _radius: number;

  constructor(radius: number) {
    this._radius = radius;
  }

  get radius(): number {
    return this._radius;
  }

  set radius(value: number) {
    if (value > 0) {
      this._radius = value;
    } else {
      throw new Error("Radius must be positive.");
    }
  }

  get area(): number {
    return Math.PI * this._radius * this._radius;
  }
}

const circle = new Circle(5);
console.log(circle.radius); // 输出: 5
circle.radius = 10;
console.log(circle.radius); // 输出: 10
console.log(circle.area); // 输出: 314.1592653589793
// circle.radius = -1; // 抛出错误: Radius must be positive.

在这个例子中,Circle 类使用存取器属性来确保 radius 属性始终为正数,并提供了一个只读的 area 属性来计算圆的面积。

示例 2: 只读属性

typescript
class Book {
  private _title: string;

  constructor(title: string) {
    this._title = title;
  }

  get title(): string {
    return this._title;
  }
}

const book = new Book("TypeScript Handbook");
console.log(book.title); // 输出: TypeScript Handbook
// book.title = "New Title"; // 错误: 设置器不存在

在这个例子中,Book 类的 title 属性是只读的,因为它只有 get 方法而没有 set 方法。

示例 3: 只写属性

虽然不常见,但你也可以创建只有 set 方法的属性:

typescript
class User {
  private _name: string;

  set name(value: string) {
    this._name = value;
  }

  greet() {
    console.log(`Hello, ${this._name}`);
  }
}

const user = new User();
user.name = "Alice";
user.greet(); // 输出: Hello, Alice
// console.log(user.name); // 错误: 获取器不存在

在这个例子中,User 类的 name 属性是只写的,因为它只有 set 方法而没有 get 方法。

4. 应用场景

存取器属性非常适合以下场景:

  • 数据验证:在设置属性值时进行验证,确保数据的有效性和一致性。
  • 懒加载:延迟初始化复杂的数据结构,直到它们真正被需要时才进行计算。
  • 封装内部状态:隐藏类的内部实现细节,防止外部代码直接访问或修改私有属性。
  • 计算属性:基于其他属性或外部条件动态计算属性值。

5. 注意事项

  • 性能考虑:存取器属性会在每次访问或设置属性时调用相应的方法,因此可能会引入一定的性能开销。对于频繁访问的属性,应权衡其利弊。
  • 调试难度:由于存取器属性的行为可能隐藏在方法内部,这有时会增加调试的难度。确保在必要时添加适当的日志或断点。
  • 兼容性:存取器属性是 ES5 标准的一部分,现代浏览器和 Node.js 环境都支持它们。但在一些旧环境中,可能需要编译或转译。

6. 总结

存取器属性是 TypeScript 和 JavaScript 中非常有用的特性,它们允许你通过 getset 方法来控制属性的访问和修改行为。合理使用存取器属性可以增强代码的封装性和灵活性,使你的代码更加健壮和易于维护。

Released under the MIT License.