Proxy 通过拦截 get、set、has、ownKeys、getOwnPropertyDescriptor 和 deleteProperty 等操作,实现对对象属性访问的精细控制,创建代理层而不修改原对象。

Proxy 可以在读取、设置、删除对象属性等操作发生时进行拦截,从而实现对属性访问的精细控制。它不是修改原对象,而是创建一个“代理层”,所有对外暴露的操作都经过这个层处理。
get:拦截属性读取
当访问对象属性(obj.prop 或 obj['prop'])时触发。可用来做默认值返回、权限检查、日志记录等。
基本用法:
const target = { name: 'Alice', age: 30 };
const proxy = new Proxy(target, {
get(obj, prop, receiver) {
console.log(`正在读取属性: ${prop}`);
if (!(prop in obj)) return '该属性不存在';
return Reflect.get(obj, prop, receiver);
}
});
console.log(proxy.name); // 输出:正在读取属性: name → 'Alice'
console.log(proxy.city); // 输出:正在读取属性: city → '该属性不存在'
注意:receiver 是当前 Proxy 实例,用于正确处理 this 指向(尤其在 getter 中调用原型方法时);推荐优先使用 Reflect.get() 而非直接 obj[prop],以保持语义一致性和原型链兼容性。
立即学习“Java免费学习笔记(深入)”;
set:拦截属性赋值
当执行 obj.prop = value 或 obj['prop'] = value 时触发。可用于数据校验、只读限制、响应式更新等。
示例:禁止写入非法属性名
const proxy = new Proxy({}, {
set(obj, prop, value, receiver) {
if (prop === 'password') {
console.warn('密码字段不允许直接设置');
return false; // 拦截赋值
}
obj[prop] = value;
console.log(`已设置 ${prop}:`, value);
return true; // 必须返回 true 表示成功
}
});
proxy.name = 'Bob'; // ✅ 正常设置
proxy.password = '123'; // ⚠️ 警告 + 赋值失败
关键点:
- 必须显式返回 true 才算赋值成功,否则会抛出 TypeError(严格模式下)
- 建议用 Reflect.set() 替代直接赋值,便于统一处理和继承逻辑
- 可结合 Object.defineProperty 或 defineProperty trap 控制更底层行为
has / ownKeys / getOwnPropertyDescriptor:影响 in、Object.keys() 等行为
这些 trap 共同决定对象的“可见性”和“枚举性”。比如隐藏某些属性、模拟稀疏数组、或实现动态键列表。
常见组合用法:
const hidden = ['internalId', '_cache'];
const target = { id: 1, name: 'Test', internalId: 1001, _cache: {} };
const proxy = new Proxy(target, {
has(obj, prop) {
return !hidden.includes(prop) && prop in obj;
},
ownKeys(obj) {
return Object.keys(obj).filter(k => !hidden.includes(k));
},
getOwnPropertyDescriptor(obj, prop) {
if (hidden.includes(prop)) return undefined;
return Object.getOwnPropertyDescriptor(obj, prop);
}
});
console.log('internalId' in proxy); // false
console.log(Object.keys(proxy)); // ['id', 'name']
这样外部代码就无法感知被屏蔽的属性,适合封装私有字段或构建透明代理接口。
deleteProperty:拦截 delete 操作
控制是否允许通过 delete obj.prop 删除属性。可用于冻结关键字段、触发清理逻辑等。
示例:保护配置项不被误删
const config = { apiUrl: 'https://api.example.com', timeout: 5000 };
const proxy = new Proxy(config, {
deleteProperty(obj, prop) {
if (['apiUrl', 'timeout'].includes(prop)) {
console.error(`禁止删除受保护配置项: ${prop}`);
return false;
}
return delete obj[prop];
}
});
delete proxy.apiUrl; // ❌ 报错提示,未删除
delete proxy.debug; // ✅ 成功删除(如果存在)
与 set 类似,需返回布尔值表示操作是否成功;返回 false 在严格模式下会抛出异常。


















