在es6 class中,getter和setter是可控的数据拦截机制,访问或赋值属性时自动触发逻辑;需避免同名属性的递归调用,推荐配合私有字段#name实现安全封装。

在 ES6 class 中,getter 和 setter 不是语法糖,而是真正可控的数据拦截机制——访问属性时自动触发逻辑,赋值时强制校验,既保持调用简洁(p.name),又守住数据边界。
语法写法:干净直接,无需操作原型
定义在 class 内部即可,自动挂载到原型,所有实例共享:
-
getter:用
get 属性名() { return ... },读取obj.prop时执行 -
setter:用
set 属性名(value) { ... },赋值obj.prop = x时执行 - 不需
Object.defineProperty,也不用手动改prototype
核心用途:不只是“看起来像属性”
它们让属性访问变成可编程的过程:
- 读取时做格式化:比如
get age() { return this._age.toString().padStart(2, '0') },返回"05"而非5 - 写入时做校验:比如检查是否为数字、是否在合理范围内,非法值直接
throw或console.warn - 隐藏真实存储字段:用
this._name存值,对外暴露name访问器,实现封装 - 支持只读或只写:只写
get就不可赋值;只写set则读取返回undefined
关键避坑:两个高频错误必须绕开
稍不留神就会导致报错或死循环:
- getter 内不能直接读同名属性:如
get name() { return this.name }→ 无限递归,爆栈 - setter 内不能直接赋同名属性:如
set name(v) { this.name = v }→ 同样触发自身,死循环 - 正确做法是搭配私有字段(
#name)或约定命名的内部字段(this._name) - setter 参数建议用语义名(如
newName),避免与局部变量混淆
配合私有字段:现代封装的推荐组合
ES2022+ 支持真正的私有字段 #name,和 getter/setter 天然契合:
- 私有字段必须在类体顶部声明:
#name; #age; - getter 直接读
this.#name,setter 校验后写入this.#age = value - 外部无法访问
p.#name,只能走访问器,彻底隔绝非法修改 - 比下划线约定更安全,且被引擎原生保护











