
2025-01-27 日报 Day79

今日的鸡汤
没有谁的生活是一帆风顺,许多人都是在一路的披荆斩棘中,摸索属于自己的那一条路。
今日学习内容
1、JS 红皮书 P273-275 第九章:代理与反射
今日笔记
1、代理可以拦截反射 API 的操作,而这意味着完全可以创建一个代理,通过它去代理另一个代理。这样就可以在一个目标对象之上构建多层拦截网:
1 | const target = { |
2、代理问题与不足:
- 代理中的 this: 代理潜在的一个问题来源是 this 值。我们知道,方法中的 this 通常指向调用这个方法的对象:
1 | const target = { |
1 | const wm = new WeakMap(); |
- 代理与内部槽位: 代理与内置引用类型(比如 Array)的实例通常可以很好地协同,但有些 ECMAScript 内置类型可能会依赖代理无法控制的机制,结果导致在代理上调用某些方法会出错。
一个典型的例子就是 Date 类型。根据 ECMAScript 规范,Date 类型方法的执行依赖 this 值上的内部槽位[[NumberDate]]。代理对象上不存在这个内部槽位,而且这个内部槽位的值也不能通过普通的 get()和 set()操作访问到,于是代理拦截后本应转发给目标对象的方法会抛出 TypeError:
1 | const target = new Date(); |
3、代理捕获器与反射方法: 代理可以捕获 13 种不同的基本操作。这些操作有各自不同的反射 API 方法、参数、关联 ECMAScript 操作和不变式。
- get(): get()捕获器会在获取属性值的操作中被调用。对应的反射 API 方法为 Reflect.get()。
1 | const myTarget = {}; |
- 返回值
返回值无限制。 - 拦截的操作
proxy.property
proxy[property]
Object.create(proxy)[property]
Reflect.get(proxy, property, receiver) - 捕获器处理程序参数
target:目标对象。
property:引用的目标对象上的字符串键属性。①
receiver:代理对象或继承代理对象的对象。 - 捕获器不变式
如果 target.property 不可写且不可配置,则处理程序返回的值必须与 target.property 匹配。
如果 target.property 不可配置且[[Get]]特性为 undefined,处理程序的返回值也必须是 undefined。
- set(): set()捕获器会在设置属性值的操作中被调用。对应的反射 API 方法为 Reflect.set()。
1 | const myTarget = {}; |
- 返回值
返回 true 表示成功;返回 false 表示失败,严格模式下会抛出 TypeError。 - 拦截的操作
proxy.property = value
proxy[property] = value
Object.create(proxy)[property] = value
Reflect.set(proxy, property, value, receiver) - 捕获器处理程序参数
target:目标对象。
property:引用的目标对象上的字符串键属性。
value:要赋给属性的值。
receiver:接收最初赋值的对象。 - 捕获器不变式
如果 target.property 不可写且不可配置,则不能修改目标属性的值。
如果 target.property 不可配置且[[Set]]特性为 undefined,则不能修改目标属性的值。
在严格模式下,处理程序中返回 false 会抛出 TypeError。