← 返回目录

13. Proxy

Proxy 想成给对象请的"经纪人":以后你碰原对象之前,都得先经过经纪人这一关——读属性走 get 拦截器,写属性走 set 拦截器,经纪人能拦你、能加工、能把关。你看到的还是那个对象,但所有读写都被偷偷监控了。

13.1 互动演示(数据校验)

给 user 设置 age:
填负数点"设置 age",看 Proxy 怎么拦截。

13.2 知识点讲解

① 没有代理 vs 有代理

没有经纪人时,你直接摸原对象,摸到啥是啥;有了经纪人后,每一次读写都先过 handler 里的规则。

// 没有代理:直接拿结果,拦不住
let target = { name: "John" }; // 原对象,没有经纪人
console.log(target.age); // undefined(什么都没有)

// 有代理:每次读都先过 handler.get
let handler = {              // 经纪人的规则本
  get(target, prop) { // 拦截"读"这个动作
    if (prop === "age") return 30; // 读 age 就直接返回 30
    return target[prop]; // 其他属性照原样读
  }
};
let proxy = new Proxy(target, handler); // 包一层经纪人
console.log(proxy.age); // 30(被经纪人加工了)

new Proxy(原对象, 经纪人规则) 生成代理对象。以后操作一律用 proxy,不要再直接碰 target——直接碰就绕过经纪人了,拦截规则白写。

② set:拦截"写"属性(记日志 / 校验)

经纪人不仅拦"读",还拦"写"。往对象上塞属性时,先问一句"这合法吗"。

let handler = {                  // 经纪人规则本
  set(target, prop, value) { // 拦截"写"
    console.log("有人要把 " + prop + " 改成 " + value); // 先记个日志
    target[prop] = value; // 真正写进去
    return true; // 表示放行
  }
};
let proxy = new Proxy(target, handler); // 包一层
proxy.skill = "前端";                    // 写属性会先被 set 拦住
// 打印:有人要把 skill 改成 前端

③ 真实用途:数据校验(把好关)

最常见的实战场景:不允许 age 被设成负数。set 里判断一下,不合规就拒绝写入。

let user = { age: 20 };      // 原对象,年龄 20
let handler = {              // 经纪人规则本
  set(target, prop, value) { // 拦截写
    if (prop === "age" &amp;&amp; value < 0) { // 要写的是 age 且是负数
      console.log("年龄不能是负数!"); // 报警
      return false; // ★ 拒绝这次写入
    }
    target[prop] = value; // 合法才真写
    return true;          // 放行
  }
};
let proxy = new Proxy(user, handler); // 包一层经纪人

proxy.age = -5; // 想写成负数,被拦下
// 打印:年龄不能是负数!
console.log(proxy.age); // 20(没写进去)

setreturn false 表示"拒绝这次写入"(严格模式下还会抛错)。Vue 3 的响应式原理就是用 Proxy 拦截读写、数据一变就自动更新界面——理解它等于摸到响应式框架的门。

13.3 实战:用在哪 / 常见坑 / 怎么解决

① 可能在什么地方用:表单数据校验(不合法就拒写)、给对象读写加日志、Vue 3 响应式原理、实现"只读"对象、数据懒加载/默认值兜底。

② 常见的问题:创建代理后还直接用原对象导致拦截不生效;set 里忘了 return trueget 里循环引用导致死循环。

③ 解决思路:只通过 proxy 访问对象;set 放行时务必 return trueget 里要返回对象时记得返回 Reflect.get(...) 或原对象属性,别在拦截器里又触发自己。

一句话:Proxy = 给对象请个经纪人,读走 get、写走 set,能拦截、能加工、能把关。