javascript中getter/setter通过访问器特性拦截属性读写,object.defineproperty()或类中get/set语法定义,proxy则适合批量拦截及全面操作捕获。

JavaScript 中通过 Getter 与 Setter 实现属性拦截,本质是利用对象属性的访问器(accessor)特性,在读取或写入属性时插入自定义逻辑,从而控制、验证或响应数据变化。
定义 Getter 与 Setter 拦截单个属性
使用 Object.defineProperty() 或字面量中的 get/set 语法,为对象属性添加访问器函数。此时该属性不再存储值,而是每次访问都触发对应函数:
- Getter 在读取属性时执行,返回值即为属性值;
- Setter 在赋值时执行,参数是新值,可用于校验、转换或触发副作用。
例如:
const obj = {};
Object.defineProperty(obj, 'age', {
get() { return this._age; },
set(value) {
if (typeof value === 'number' && value >= 0) {
this._age = value;
} else {
throw new Error('age must be a non-negative number');
}
}
});
这样对 obj.age 的读写都会被拦截,且底层用 _age 存储真实值。
在类中使用 Getter/Setter 封装实例属性
ES6 类支持在原型上直接声明访问器,更符合面向对象习惯。注意:类中的 getter/setter 默认定义在原型上,不占用每个实例的内存:
class Person {
constructor(name) {
this._name = name;
}
get name() {
console.log('Getting name...');
return this._name;
}
set name(value) {
if (typeof value === 'string' && value.trim()) {
console.log('Setting name to:', value);
this._name = value.trim();
}
}
}
创建实例后,person.name 的每次访问都会触发对应逻辑,适合做日志、格式化或权限检查。
批量拦截多个属性:Proxy 更适合复杂场景
Getter/Setter 适合拦截已知属性,但无法监听新增或删除属性,也不能捕获 in、delete 等操作。若需全面拦截(如实现响应式系统),应优先考虑 Proxy:
- Proxy 可拦截 get、set、has、deleteProperty、ownKeys 等 13 种操作;
- 它作用于整个对象,无需提前声明属性;
- 配合 Reflect 可轻松实现透明代理和默认行为转发。
简单示例:
const handler = {
get(target, prop) {
console.log(`Get ${prop}`);
return target[prop];
},
set(target, prop, value) {
console.log(`Set ${prop} = ${value}`);
target[prop] = value;
return true;
}
};
const proxy = new Proxy({}, handler);
此时对 proxy.xxx 的任意读写都会被统一处理,灵活性远超单个 setter/getter。
注意事项与常见陷阱
使用访问器时需避免常见错误:
- 不要在 getter 中直接返回自身(如 return this.prop),否则触发无限递归;
- setter 中修改同一属性需用私有字段(如 this._prop)存储,否则又会触发自身 setter;
- getter/setter 不会出现在 for...in 或 Object.keys() 中(除非 configurable: true 且 enumerable: true);
- 使用 Object.assign() 或展开运算符复制对象时,访问器不会被继承,只会拷贝其返回值。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











