es6类中getter/setter是定义在原型上的访问器属性,通过属性读写语法自动触发拦截逻辑;它们在类定义时即写入原型描述符,需用私有字段或下划线命名避免递归,并支持数据校验、自动转换、副作用触发等场景。

ES6 类里的 getter 和 setter 本质是定义在原型上的访问器属性,它们不是普通方法,而是通过属性读写语法自动触发的拦截逻辑——读取时走 get,赋值时走 set,整个过程对调用者完全透明。
核心机制:靠访问器属性实现拦截
getter/setter 不是运行时动态添加的钩子,而是在类定义阶段就写入原型对象的属性描述符中。当你写 get name(),JavaScript 实际在 MyClass.prototype 上为 name 属性设置了 get 和 set 函数。每次访问 instance.name 或赋值 instance.name = xxx,引擎就会查到这个描述符并执行对应函数。
- 必须成对或单独存在:可以只有 get(只读)、只有 set(只写,极少用),或两者都有(可读写)
- 不能和同名普通属性共存:比如在 constructor 里用
this.name = 'xxx',再定义get name(),会报错 - 内部需用不同名字段存储真实值:如
#name或_name,否则 set 中赋值this.name = value会再次触发自身,导致无限递归
怎么正确声明并避免常见错误
推荐使用私有字段(#前缀)作为底层存储,语义清晰且天然防递归:
- 定义私有字段:
#age = 0在类体顶部声明 - setter 中只操作
this.#age,绝不出现this.age - getter 直接返回
this.#age,也可加格式化逻辑(如转字符串、加单位) - 若用下划线约定(如
_age),务必确认所有赋值都指向this._age,而不是this.age
典型拦截场景与写法示例
拦截不只是“挡一下”,而是把业务逻辑自然嵌入属性操作中:
- 数据校验:set 中检查类型、范围、格式,非法值直接 throw 或静默处理
-
自动转换:比如把传入的字符串 age 用
Number()转换,再判断是否有效 - 副作用触发:赋值后自动更新关联状态、发日志、通知视图刷新
-
计算属性封装:get 中返回基于其他字段运算的结果,如
get fullName() { return this.firstName + ' ' + this.lastName; }
它能拦截什么,不能拦截什么
getter/setter 只对**已明确声明的属性名**生效:
- ✅ 对
obj.prop读写有效 - ✅ 支持 for...in、Object.keys 等枚举(因为它是原型上的自有属性)
- ❌ 无法拦截未定义属性的访问(如
obj.unknown不会触发任何 getter) - ❌ 无法监听动态新增属性(除非提前定义好访问器)
- ❌ 不适用于原生宿主对象(如 localStorage、window),需用 Proxy 封装代理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











