在 TypeScript 中使用 getter 和 setter

在 TypeScript 中使用 getter 和 setter

Using getters and setters in TypeScript

使用getandset关键字在 TypeScript 中定义 getter 和 setter。

Getters 使我们能够将属性绑定到访问属性时调用的函数,而 setter 将属性绑定到尝试设置属性时调用的函数。

索引.ts
class Developer { private _language = ''; private _tasks: string[] = []; get language() { return this._language; } set language(value: string) { this._language = value; } get tasks() { return this._tasks; } set tasks(value: string[]) { this._tasks = value; } } const dev = new Developer(); dev.language = 'TypeScript'; console.log(dev.language); // 👉️ "TypeScript" dev.tasks = ['develop', 'test']; dev.tasks.push('ship'); console.log(dev.tasks); // ['develop', 'test', 'ship']

该类Developer有 2 个
getter 和 setter

get语法将

一个对象属性绑定到一个函数,因此每次访问该属性时,都会调用该函数。

当我们访问language实例的属性时
,我们正在调用该方法。
language()

set语法将

一个对象属性绑定到一个函数,每次尝试设置该属性时,都会调用该函数。

值得注意的是,尽管我们在后台调用类方法,但我们使用 getter 和 setter 就像我们在对象上使用常规属性一样。

您不应尝试将 setter 调用为myInstance.mySetter('TypeScript'),而应将属性设置为myInstance.mySetter = 'TypeScript'

请注意,我们
在类中声明
属性时使用了
private
关键字。
_language_tasks

索引.ts
class Developer { private _language = ''; private _tasks: string[] = []; get language() { return this._language; } set language(value: string) { this._language = value; } get tasks() { return this._tasks; } set tasks(value: string[]) { this._tasks = value; } }

具有私有可见性的类成员

只能在类本身内部访问。

这很重要,因为我们不希望我们类的消费者能够访问_language_tasks属性。

索引.ts
class Developer { private _language = ''; private _tasks: string[] = []; get language() { return this._language; } set language(value: string) { this._language = value; } get tasks() { return this._tasks; } set tasks(value: string[]) { this._tasks = value; } } const dev = new Developer(); // ⛔️ Error: Property '_language' is private // and only accessible within class 'Developer'.ts(2341) console.log(dev._language);

尝试private从类外部访问属性会导致错误,这正是我们需要的,以确保消费者按预期使用 getter 和 setter。

使用下划线前缀,因为我们需要为属性取一个不同的名称,以避免 getter 和 setter 方法中的无限循环。

以下实现会导致无限循环。

索引.ts
class Developer { private language = 'TypeScript'; set language(value: string) { // ⛔️ Error: Maximum call stack exceeded this.language = value; } } const dev = new Developer();

代码中的问题是——我们没有使用下划线
language作为类中属性的前缀。

因此,每次调用 setter 时,它都会设置属性并在每次设置属性时继续调用自身。

如果您仅为特定属性定义 getter,则该属性会自动标记为readonly.

索引.ts
class Developer { private _language = 'TypeScript'; get language() { return this._language; } } const dev = new Developer(); console.log(dev.language); // 👉️ "TypeScript" // ⛔️ Cannot assign to 'language' because //it is a read-only property.ts(2540) dev.language = 'TypeScript';

我们只为属性分配了一个 getter language,因此不能重新分配。

如果您没有显式键入 setter 参数,TypeScript 可以从 getter 的返回类型中推断出它。

索引.ts
class Developer { private _language = ''; get language() { return this._language; } // 👇️ (parameter) value: string (inferred) // from getter return type set language(value) { this._language = value; } } const dev = new Developer(); dev.language = 'TypeScript'; console.log(dev.language); // 👉️ "TypeScript"

即使我们没有value在 setter 中显式键入参数,TypeScript 仍然知道它是 type string,因为languagegetter 返回一个 type 的值string

您还可以设置在实例化类时使用 getter 和 setter 的属性的值。

索引.ts
class Developer { private _language = ''; // 👇️ use a constructor method constructor(language: string) { this.language = language; } get language() { return this._language; } set language(value: string) { this._language = value; } } const dev = new Developer('TypeScript'); console.log(dev.language); // 👉️ "TypeScript" dev.language = 'JavaScript'; console.log(dev.language); // 👉️ "JavaScript"

constructor方法在类被实例化时被调用。该方法采用language参数并使用已定义的 setter 初始化其值。

_language如果您不想使用 setter 来初始化构造函数中的属性,您也可以使用该属性。

索引.ts
class Developer { private _language = ''; constructor(language: string) { // 👇️ Not using setter (_language instead of language) this._language = language; } get language() { return this._language; } set language(value: string) { this._language = value; } } const dev = new Developer('TypeScript'); console.log(dev.language); // 👉️ "TypeScript" dev.language = 'JavaScript'; console.log(dev.language); // 👉️ "JavaScript"

上面的示例没有使用 setter 方法为
language属性设置初始值,因为我们在属性前加了下划线。