JavaScript中getter/setter是定义在原型或对象上的访问器属性,通过属性读写自动触发拦截逻辑;需用私有字段或下划线命名避免递归,支持数据校验、自动转换、副作用触发及计算属性封装,但仅对显式声明的属性生效,无法拦截未定义属性或原生宿主对象。

JavaScript 中的 getter 和 setter 是通过定义访问器属性来拦截对象属性的读写操作,不是普通方法,而是由引擎在属性访问时自动触发的拦截逻辑——读取走 get,赋值走 set,调用方完全无感。
核心机制:访问器属性写在原型或对象自身上
当你用 class 定义 get name() 或用 Object.defineProperty(obj, 'age', { get() {}, set(v) {} }),JS 实际是在目标位置(类的 prototype 或该对象)为该属性注册了访问器描述符。每次执行 obj.age 或 obj.age = 25,引擎就会查到这个描述符并运行对应函数。
- 必须用不同名字段存储真实值,比如私有字段
#age或约定命名的_age;否则this.age = value在 set 里会再次触发 set,造成无限递归 - 不能和同名数据属性共存:如果已在 constructor 里写了
this.name = 'Tom',再定义get name()会报错 - 可以单独存在——只有 get 是只读属性,只有 set 是只写(极少用),两者都有则是可读写
常见拦截场景与写法示例
拦截不是为了“挡住”,而是把业务逻辑自然嵌入属性操作中:
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
-
数据校验:在 set 中检查类型、范围、格式,非法值可
throw或静默处理(如年龄非正整数则忽略) -
自动转换:把传入的字符串
"25"用Number()转成数字,再判断是否有效 - 副作用触发:赋值后自动更新关联字段、发日志、通知视图刷新(Vue 2 的响应式即基于此)
-
计算属性封装:get 中返回组合结果,例如
get fullName() { return this.firstName + ' ' + this.lastName; }
它能拦什么,不能拦什么
getter/setter 的作用范围是明确声明过的属性名,有清晰边界:
立即学习“Java免费学习笔记(深入)”;
- ✅ 对
obj.prop、obj['prop']读写有效 - ✅ 支持
for...in、Object.keys()等枚举(因它是原型或对象上的自有属性) - ❌ 无法拦截未定义属性的访问(如
obj.unknown不会触发任何 getter) - ❌ 不适用于原生宿主对象(如
localStorage、window),这些需用Proxy封装代理 - ❌ 无法监听动态新增属性,除非提前定义好访问器
怎么写才安全可靠
推荐优先使用 ES6 私有字段语法,语义清晰且天然防递归:
- 在类体顶部声明
#age = 0 - set 中只操作
this.#age,绝不出现this.age - get 中直接返回
this.#age,也可加格式化(如返回this.#age + '岁') - 若用下划线约定(如
_age),所有赋值必须统一指向this._age,否则极易出错

















