红宝书第二十讲:详解JavaScript的Proxy与Reflect
资料取自《JavaScript高级程序设计(第5版)》。
查看总目录:红宝书学习大纲
一、Proxy的作用:给对象戴上“监听耳机”
Proxy(代理)允许你为对象创建代理层,拦截并自定义对象的基本操作(如属性读写、函数调用等)。核心用法:
示例1:拦截属性读取
// 创建目标对象
const target = { name: '小明', age: 18 };
// 定义代理处理器(拦截读取)
const handler = {
get(target, property) {
console.log(`有人在读取属性:${property}`);
return Reflect.get(...arguments); // 利用Reflect执行默认操作
}
};
// 创建代理对象
const proxy = new Proxy(target, handler);
console.log(proxy.name); // 输出:有人在读取属性 name → 小明
1: 资料1说明Proxy是目标对象的抽象层
2: 资料3展示使用Reflect执行默认行为
二、常见拦截操作(陷阱)
Handler对象可以定义多种陷阱,常用方法:
- get() → 拦截属性读取
- set() → 拦截属性设置
- apply() → 拦截函数调用
- has() → 拦截
in
操作符
示例2:拦截属性写入并进行验证
const validator = {
set(target, prop, value) {
if (prop === 'age' && typeof value !== 'number') {
throw new Error('年龄必须是数字!');
}
return Reflect.set(target, prop, value); // 通过Reflect正确设置值
}
};
const proxy = new Proxy({}, validator);
proxy.age = 20; // 正常
proxy.age = '20';// 抛出错误:年龄必须是数字!
3: 资料4说明陷阱如何配合Reflect使用
三、Reflect:Proxy的最佳搭档
Reflect API提供与Proxy陷阱同名的方法,用于执行默认操作24。优势:
- 避免手动处理底层对象
- 保持代码简洁性
示例3:简化代理的默认行为
// 完全透传的代理(所有操作自动反射到目标对象)
const target = { secret: 'test123' };
const proxy = new Proxy(target, Reflect); // 直接使用Reflect处理所有陷阱
console.log(proxy.secret); // test123(所有操作原样执行)
4: 资料6演示通过Reflect创建透传式代理
四、核心应用场景
- 数据验证(如示例2中的年龄验证)
- 日志记录(记录属性访问或修改)
- 动态扩展功能(自动生成属性或方法)
示例4:记录数组push操作
const array = [];
const handler = {
get(target, prop) {
if (prop === 'push') {
return function(...args) {
console.log(`添加了元素:${args}`);
return Reflect.apply(target[prop], target, args); // 调用原始的push方法
};
}
return Reflect.get(...arguments);
}
};
const proxyArray = new Proxy(array, handler);
proxyArray.push(1, 2); // 输出:添加了元素:1,2 → 数组变为[1,2]
3: 资料4展示如何通过代理拦截数组方法
五、注意事项与规则
示例5:陷阱不变式错误
const handler = {
defineProperty() { // 未正确返回布尔值
console.log('尝试定义属性');
// 未调用Reflect.defineProperty
}
};
const proxy = new Proxy({}, handler);
Object.defineProperty(proxy, 'foo', { value: 'bar' }); // 抛出TypeError
5: 资料5指出未正确使用Reflect方法可能导致错误
流程图:Proxy与Reflect协作流程
目录:总目录
上篇文章:红宝书第十九讲:详解JavaScript的Fetch API与Ajax请求
下篇文章:红宝书第二十一讲:详解JavaScript的模块化(CommonJS与ES Modules)
脚注
- 《JavaScript高级程序设计(第5版)》说明Proxy是目标对象的抽象层 ↩
- 《JavaScript高级程序设计(第5版)》展示Reflect方法简化默认操作 ↩
- 《JavaScript高级程序设计(第5版)》演示如何拦截数组的push操作 ↩
- 《JavaScript高级程序设计(第5版)》提供使用Reflect创建透传代理的示例 ↩
- 《JavaScript高级程序设计(第5版)》指出陷阱方法需遵守严格规则 ↩
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。