当前位置: 首页 > news >正文

红宝书第二十讲:详解JavaScript的Proxy与Reflect


红宝书第二十讲:详解JavaScript的Proxy与Reflect

资料取自《JavaScript高级程序设计(第5版)》。
查看总目录:红宝书学习大纲


一、Proxy的作用:给对象戴上“监听耳机”

Proxy(代理)允许你为对象创建代理层,拦截并自定义对象的基本操作(如属性读写、函数调用等)。核心用法:

  • 通过new Proxy(target, handler)创建代理对象
  • handler对象定义各种监听方法(称为陷阱/trap)1[^2]
示例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创建透传式代理


四、核心应用场景
  1. 数据验证(如示例2中的年龄验证)
  2. 日志记录(记录属性访问或修改)
  3. 动态扩展功能(自动生成属性或方法)
示例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展示如何通过代理拦截数组方法


五、注意事项与规则
  • 必须遵守陷阱不变式(Trap Invariants)→ 例如.defineProperty()必须返回布尔值 5
  • 代理无法完全模拟目标对象(如某些内部属性无法拦截)1
示例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)

脚注


  1. 《JavaScript高级程序设计(第5版)》说明Proxy是目标对象的抽象层 ↩︎ ↩︎ ↩︎

  2. 《JavaScript高级程序设计(第5版)》展示Reflect方法简化默认操作 ↩︎ ↩︎

  3. 《JavaScript高级程序设计(第5版)》演示如何拦截数组的push操作 ↩︎ ↩︎

  4. 《JavaScript高级程序设计(第5版)》提供使用Reflect创建透传代理的示例 ↩︎ ↩︎

  5. 《JavaScript高级程序设计(第5版)》指出陷阱方法需遵守严格规则 ↩︎ ↩︎

http://www.dtcms.com/a/98552.html

相关文章:

  • 【自学笔记】Go语言基础知识点总览-持续更新
  • Sentinel 相关知识点
  • 【第34节】windows原理:PE文件的导出表和导入表
  • Linux 文件系统全解析
  • 202518 | Ngnix
  • MAUI开发Device.BeginInvokeOnMainThread使用
  • python专题1-----判断一个变量是否是字符串类型
  • 代码随想录算法训练营--打卡day4
  • windows第二十章 单文档应用程序
  • 基于大语言模型的智能音乐创作系统——从推荐到生成
  • Jenkins教程(自动化部署)
  • 纯个人整理,蓝桥杯使用的算法模板day1(dfs、bfs)
  • Axure疑难杂症:完美解决中继器筛选问题(时间条件筛选、任性筛选)
  • 信号与系统(郑君里)第一章-绪论 1-22 课后习题解答
  • jdk 支持路线图
  • gamma函数与zeta函数的关系
  • 【大数据技术】大数据技术概念及概述
  • QT音乐播放器(1):数据库保存歌曲
  • Vue Kubernetes项目 局部布局面包屑 el-breadcrumb
  • Matlab教程004:Matlab矩阵的拼接重构重排以及矩阵的运算
  • 测试测试 测试
  • Kubernetes》k8s》Containerd 、ctr 、cri、crictl
  • 每日一题 MySQL基础知识----(四)
  • Java 大视界 -- Java 大数据机器学习模型在电商商品推荐冷启动问题中的解决策略(160)
  • [Python学习日记-88] 并发编程之多进程 —— 队列与生产者消费者模型
  • 赛博威智慧导购平台,融合AI激活一线导购效能,破局增长瓶颈
  • 目标识别与双目测距(1)环境搭建:Ubuntu+yolov5+pcl库
  • JAVA学习*工厂模式
  • Python容器详解:从字符串到字典的完整指南
  • CPT204 Advanced Obejct-Oriented Programming 高级面向对象编程 Pt.4 泛型