← 返回目录

第 12 卷

第 12 / 19 卷日期:

(3)Proxy工作示例

Code block

1 2// 1. 定义目标对象

3const targetObj = { 4name: "张三",

5age: 20 6};

7 8// 2. 定义拦截器对象

9const handler = { 10// 拦截属性读取

11get(target, prop) {

12console.log(`读取属性${prop}:`, target[prop]);
13//若属性不存在,返回默认值,而非undefined
14return prop in target ? target[prop] : "默认值";
15},
16//拦截属性赋值
17set(target, prop, value) {
18console.log(`赋值属性${prop}:`, value);
19//对age属性进行赋值校验
20if (prop === "age" && (typeof value !== "number" || value < 0)) {
21throw new Error("年龄必须是大于0的数字");
22}
23//将赋值操作传递给目标对象
24target[prop] = value;
25return true; //表示赋值成功(必须返回布尔值,否则严格模式报错)
26},
27//拦截in运算符
28has(target, prop) {
29console.log(`判断${prop}是否存在`);
30return prop in target;
31},
32//拦截delete操作
33deleteProperty(target, prop) {
34console.log(`删除属性${prop}`);
35delete target[prop];
36return true;
37}

44console.log(proxyObj.name); // 读取属性name:张三 → 输出张三 45console.log(proxyObj.gender); // 读取属性gender:undefined → 输出默认值

46 47proxyObj.age = 25; // 赋值属性age:25 → targetObj.age=25

48// proxyObj.age = -10; // 报错:年龄必须是大于0的数字 49

50console.log("name" in proxyObj); //判断name是否存在→输出true
51delete proxyObj.age; //删除属性age→targetObj.age被删除
52console.log(proxyObj.age); //读取属性age:undefined→输出默认值

(4)Proxy的常见使用场景

  1. 数据校验与过滤:拦截对象属性的赋值操作,对传入的值进行类型、范围等校验,确保数据合法

性,适用于表单验证、配置项校验等场景。

  1. 数据响应式(框架核心):是Vue3、React等框架实现响应式的核心技术,通过拦截对象的属性读

取和赋值,感知数据变化,进而触发视图更新。

  1. 日志记录与监控:拦截对象的各类操作(读取、赋值、删除等),记录操作日志,用于调试、性能

监控或权限审计。

  1. 对象虚拟化/懒加载:对大型对象或远程数据进行代理,仅在访问属性时才加载实际数据,减少初始

加载开销。

  1. 函数增强:代理函数对象,拦截函数调用(通过 apply 陷阱),实现参数校验、缓存结果、延迟

执行等增强功能。

21. 比较Proxy和Object.defineProperty之间的区别,特别是在用于对象

属性拦截和修改行为时,它们在功能、性能以及适用场景上有何异同?

Proxy(ES6)和 Object.defineProperty(ES5)均能实现对象属性的拦截与修改,但 Proxy 是更全面、更强大的拦截方案,二者的核心差异集中在功能覆盖、拦截粒度、使用便捷性等方

面,具体对比和说明如下:

(1)核心差异对比表

对比维度ProxyObject.defineProperty
拦截范围全面覆盖对象的所有操作:属仅能拦截属性的读取
性读取(get)、赋值(getter)和赋值
拦截粒度针对整个目标对象,一次性拦针对单个属性,需逐个为要拦
截所有属性的对应操作,无需截的属性配置getter/setter,
逐个属性配置新增属性需重新配置
目标对象类型支持任意对象类型:普通对主要支持普通对象的属性,对
象、数组、函数、Map/Set等数组的拦截需额外处理(如重

写数组方法),对函数、集合类对象支持有限

属性新增/删除拦截可通过set(新增属性赋无法直接拦截属性新增(需配
值)、deleteProperty合
(删除属性)直接拦截Object.preventExtensi

ons 等方法间接限制),也无法拦截属性删除

数组拦截支持原生支持数组的所有操作拦截无法直接拦截数组的索引赋值
(如arr[0] = 1、(如arr[0] = 1)和原型
push、splice等),无方法(如push),需重写
需额外处理数组原型方法才能实现,逻辑

复杂

使用便捷性API设计简洁,通过拦截器对配置繁琐,需逐个属性定义
象集中配置所有拦截逻辑,代getter/setter,新增属性需重
码可读性高、维护成本低复调用方法配置,代码冗余
性能表现现代浏览器优化较好,对于大ES5时代的成熟方案,对单个
多数场景性能接近属性的读写操作性能稳定,在
Object.defineProperty旧环境兼容性更好

;但在低版本浏览器或频繁操作单个属性的场景,可能略逊

兼容性仅支持ES6及以上环境(IE不支持ES5及以上环境(IE8+支支持,Edge 12+、Chrome 持,兼容性广泛)

49+支持)

(2)功能与适用场景的异同

  1. 相同点:核心作用一致

二者的核心目的都是拦截对象属性的读写行为,实现数据校验、数据响应式、日志监控等功能,是 JavaScript中实现“数据劫持”的核心技术。

全站分卷索引 · 19 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷