TypeScript中的Get和Set:轻松掌握访问器的魔力
\n\n你是否曾经在TypeScript中编写类时想过:“如果能创建一个智能属性,读取时自动计算,赋值时自动验证数据,那该多好?”那么,认识一下——getter(get)和setter(set)。它们不仅仅是语法糖,更是控制数据访问的强大工具。
\n\n如果你曾在Stack Overflow上接触过这个话题,就会知道:“get and set in TypeScript”这个问题获得了成千上万的浏览量。人们常常困惑何时使用访问器,何时使用普通方法。在本文中,我们将从基础到高级细节,逐一梳理清楚。
\n\n准备好了吗?我们开始吧!
\n\nTypeScript中的get和set是什么?
\n\nGetter是在读取属性时调用的方法。Setter是在赋值时调用的方法。它们一起构成了访问器(accessors)。使用起来就像操作普通字段一样,但底层却包含了逻辑。
\n\n这是一个最小示例:
\n\nclass User {\n private _name: string = '';\n\n get name(): string {\n return this._name;\n }\n\n set name(value: string) {\n if (value.length > 0) {\n this._name = value;\n } else {\n console.log('姓名不能为空');\n }\n }\n}\n\nconst user = new User();\nuser.name = '安娜'; // 调用set\nconsole.log(user.name); // 调用get → '安娜'\nuser.name = ''; // 尝试设置空姓名 → 控制台输出消息\n\n请注意:带有前缀_的属性_name是一个私有字段。外部无法直接访问它。相反,我们使用公共访问器name。
为什么需要getter和setter?3个主要原因
\n\n1. 数据验证
\nSetter是检查输入值的理想位置。你可以在无效数据进入对象之前将其过滤掉。
\n\nclass Temperature {\n private _celsius: number = 0;\n\n get celsius(): number {\n return this._celsius;\n }\n\n set celsius(value: number) {\n if (value < -273.15) {\n throw new Error('温度不能低于绝对零度');\n }\n this._celsius = value;\n }\n}\n\n2. 计算属性
\nGetter可以返回基于其他数据计算的结果,而不是存储的值。
\n\nclass Rectangle {\n constructor(public width: number, public height: number) {}\n\n get area(): number {\n return this.width * this.height;\n }\n\n get perimeter(): number {\n return 2 * (this.width + this.height);\n }\n}\n\nconst rect = new Rectangle(10, 5);\nconsole.log(rect.area); // 50 — 即时计算\n\n3. 封装与访问控制
\n你可以将属性设置为只读(仅getter)或只写(仅setter)。这有助于遵循面向对象编程原则。
\n\nclass Config {\n private _apiKey: string = 'secret123';\n\n get apiKey(): string {\n // 可以添加日志记录或权限检查\n return this._apiKey;\n }\n // 未定义setter — 属性只读\n}\n\nconst config = new Config();\nconsole.log(config.apiKey); // 'secret123'\n// config.apiKey = 'newKey'; // 编译错误!\n\n关于TypeScript中get和set的常见问题
\n\n让我们来解答一下初学者(以及其他人)在Stack Overflow和论坛上最常问的问题。
\n\n问题1:get/set与普通方法有何不同?
\n主要区别在于调用语法。访问器看起来像属性:没有圆括号。这使得代码更简洁、更直观。比较一下:
\n\n// 使用方法\nuser.getName();\nuser.setName('彼得');\n\n// 使用访问器\nuser.name;\nuser.name = '彼得';\n\n第二个区别是访问器不能重载(overload)。每个访问器只有一个签名