Proxy是什么
想象我们有一个房子(对象),但不想直接管理租客(操作对象)。这时你委托一个中介公司(Proxy)
- 房东(目标对象) :原始数据
- 中介(Proxy 实例) :拦截所有对房子的操作(读/写/删等)
- 租客规则(Handler 对象) :定义中介如何处理租客的请求
// 创建中介公司(Proxy)
const 中介 = new Proxy(房东, {
// 定义处理规则
收房租: (房东, 房客, 金额) => { /* 自定义逻辑 */ }
});
拦截对象操作
读取属性(get)
拦截对象属性的读取,并自定义返回值
const user = { name: "小明" };
const proxy = new Proxy(user, {
get(target, prop) {
console.log(` 有人读取了 ${prop} 属性`);
return target[prop] || "属性不存在";
}
});
console.log(proxy.name); // 输出:"有人读取了 name 属性" → "小明"
console.log(proxy.age); // 输出:"有人读取了 age 属性" → "属性不存在"
设置属性(set)
拦截属性赋值操作,可添加验证逻辑
const bank = { balance: 100 };
const proxy = new Proxy(bank, {
set(target, prop, value) {
if (prop === "balance" && value < 0) {
throw new Error("余额不能为负数!");
}
target[prop] = value; // 通过验证才赋值
return true; // 必须返回布尔值
}
});
proxy.balance = 200; // 成功
proxy.balance = -50; // 报错:余额不能为负数!
其他一些常用拦截操作
| 方法 | 作用 | 示例场景 |
|---|---|---|
deleteProperty() | 拦截 delete 操作 | 防止误删关键属性 |
has() | 拦截 in 运算符 | 隐藏私有属性(如 _password) |
ownKeys() | 拦截 Object.keys() 等 | 过滤敏感字段 |
apply() | 拦截函数调用 | 给函数调用添加日志 |
一些常见的使用场景
数据验证与保护 实现表单自动校验
const form = { username: "" };
const validator = new Proxy(form, {
set(target, prop, value) {
if (prop === "username" && value.length < 3) {
throw new Error("用户名至少3位!");
}
target[prop] = value;
return true;
}
});
validator.username = "ab"; // 报错
日志记录系统 监控对象操作轨迹
const product = { price: 100 };
const logProxy = new Proxy(product, {
get(target, prop) {
console.log(` 读取属性: ${prop}`);
return target[prop];
},
set(target, prop, value) {
console.log(` 设置 ${prop} 为 ${value}`);
target[prop] = value;
return true;
}
});
logProxy.price = 200; // 控制台输出:"设置 price 为 200"
私有属性保护 隐藏以下划线开头的属性
const data = { _secret: "123", public: "hello" };
const safeData = new Proxy(data, {
has(target, prop) {
if (prop.startsWith("_")) return false; // 隐藏私有属性
return prop in target;
},
ownKeys(target) {
return Object.keys(target).filter(k => !k.startsWith("_"));
}
});
console.log("_secret" in safeData); // false
console.log(Object.keys(safeData)); // ["public"]
Proxy vs Object.defineProperty
| 特性 | Proxy | Object.defineProperty |
|---|---|---|
| 拦截范围 | 13 种对象操作(全维度) | 仅属性读写 |
| 嵌套支持 | ✅ 需递归实现 | ❌ 需手动监听每个层级 |
| 数组支持 | ✅ 直接拦截 push/pop 等 | ❌ 需重写数组方法 |
| 兼容性 | ES6+ 浏览器 | ES5+ 浏览器 |
牢记
“Proxy 是对象中介,操作必经它把关:读属性(get)、改数据(set)、删字段(deleteProperty),还能隐身藏秘方(has/ownKeys)。”