看完这篇文章,你就知道什么是proxy

一、Proxy 是什么?

Proxy(代理)是ES6引入的一个强大的特性,它允许我们拦截并自定义对象的基本操作。简单来说,Proxy就像一个"中间人",控制对目标对象的访问。你可以通过它监控对象的属性读取、赋值、删除等操作,并在这些操作发生时插入自定义逻辑。

通俗的来讲就是想象一下你有一个朋友叫"小代",你想找某个人办事,但这个人不直接见你。你只能通过"小代"去传达你的请求,小代会帮你和那个人打交道。

在这个场景中:

  • 那个"被你找的人"就是目标对象(target)
  • "小代"就是 Proxy(代理)
  • 你要做的事情(比如:问问题、改东西、删东西),都要经过"小代"

所以,Proxy 就是一个中间人,你可以通过它来控制对某个对象的操作。


二、Proxy 的基本结构

javascript 复制代码
const proxy = new Proxy(target, handler);
  • target:你要代理的对象。
  • handler:一个配置对象,里面定义了"你想在什么时候做点什么事情"。

三、举个最简单的例子:监控属性访问

我们想监控谁在读取或修改对象的属性。

javascript 复制代码
const obj = {
  name: "张三",
  age: 20
};

const handler = {
  get(target, key) {
    console.log("有人要读取属性:" + key);
    return target[key];
  },
  set(target, key, value) {
    console.log("有人要设置属性:" + key + " 为 " + value);
    target[key] = value;
    return true; // 必须返回 true 表示设置成功
  }
};

const p = new Proxy(obj, handler);

console.log(p.name);   // 输出:有人要读取属性:name
p.age = 30;            // 输出:有人要设置属性:age 为 30

解释一下这段代码:

  • 我们创建了一个 Proxy 对象 p
  • 每次读取属性(如 p.name)都会触发 get 方法
  • 每次设置属性(如 p.age = 30)都会触发 set 方法
  • 这样我们就知道了谁在操作对象的哪些属性!

拦截器(handler)常用方法一览

get(target, key) 读取属性 obj.name
set(target, key, value) 设置属性 obj.name = 'Tom'
has(target, key) in 运算符 'name' in obj
deleteProperty(target, key) delete 操作 delete obj.name
apply(target, thisArg, args) 函数调用 fn()fn.apply()
construct(target, args) new 调用 new MyClass()

四、实际应用场景(通俗举例)

场景1:数据验证(防止乱改)

比如你希望别人不能随便把年龄改成字符串:

javascript 复制代码
const user = {
  age: 18
};

const handler = {
  set(target, key, value) {
    if (key === 'age' && typeof value !== 'number') {
      console.error('年龄必须是数字!');
      return true; // 不抛错,只是阻止赋值
    }
    target[key] = value;
    return true;
  }
};

const proxy = new Proxy(user, handler);

proxy.age = "abc"; // 输出:年龄必须是数字!
proxy.age = 25;    // 正常执行

场景2:权限控制(有些属性不能看)

比如某些私有属性不能让别人看到:

javascript 复制代码
const data = {
  username: "admin",
  _password: "123456"
};

const handler = {
  get(target, key) {
    if (key.startsWith('_')) {
      throw new Error("不能访问私有属性");
    }
    return target[key];
  }
};

const proxy = new Proxy(data, handler);

console.log(proxy.username);     // 正常输出 admin
console.log(proxy._password);    // 报错:不能访问私有属性

场景3:响应式系统(Vue3的核心原理)

Vue3用Proxy来监听数据变化,自动更新页面。

比如你改了数据,页面就自动刷新了:

javascript 复制代码
let data = {
  count: 0
};

const handler = {
  set(target, key, value) {
    console.log("数据变了,准备更新视图!");
    target[key] = value;
    return true;
  }
};

const proxy = new Proxy(data, handler);

proxy.count++; // 输出:数据变了,准备更新视图!

五、常见面试题 & 答案

Q1:Proxy 是干什么的?

答:Proxy 是用来拦截并自定义对象行为的一种机制。就像一个"中间人",我们可以在这个中间人里加一些逻辑,比如打印日志、校验数据、权限控制等。


Q2:Proxy 和 Object.defineProperty 有什么区别?

区别 Proxy Object.defineProperty
支持数组 ×
新增属性是否能监听 ×
拦截操作种类 多(13种) 少(只有get/set)
兼容性 ES6+ ES5+

Q3:Reflect 是干嘛的?为什么要和 Proxy 一起用?

答:Reflect 提供了一些默认操作的方法,比如 Reflect.get()、Reflect.set(),这样我们在 Proxy 中调用它们时可以更安全、统一,并且兼容性更好。


六、总结一句话

Proxy 就像一个"门卫",你想访问一个对象的属性或者修改它,都得先过它这一关。

你可以利用这个"门卫"来做很多事,比如:

  • 监控谁动了对象
  • 控制谁能看到什么
  • 防止错误的数据进来
  • 实现 Vue 那样的响应式系统

七、练习建议

你可以试着写几个简单的 Proxy:

  1. 拦截删除操作,让用户确认后再删除。
  2. 创建一个只读对象,不让别人修改。
  3. 统计某个对象被访问了多少次。
相关推荐
福兮说1 小时前
纯前端把图片压缩到指定体积:canvas.toBlob 配合二分查找
前端·javascript·canvas·图片处理
志尊宝1 小时前
Vue3 零基础每日笔记(018):按键与鼠标修饰符——回车搜索、Ctrl+S 保存这样写
javascript·vue.js·笔记
可乐鸡翅yeah_2 小时前
HLS流媒体首屏起播慢深度优化,从分片、索引、播放器全链路调优
开发语言·javascript·ecmascript·m3u8·m3u8在线
开开心心就好3 小时前
低年级识字练笔顺工具,电脑和安卓端都能用
前端·javascript·网络·安全·scala·erlang·语音识别
杨利杰YJlio3 小时前
ITSK PE 26U5 测试版解读:组件完善、VMD 修复与服务器支持边界
前端·javascript·后端
夏幻灵3 小时前
Vue / React 列表渲染中的 key:为什么没有 key,Checkbox 可能“对号跑错”?
前端·javascript·vue.js
YWL3 小时前
vue-time-axis-plus进阶:双进度条+跨空白续播+播放指针,打造专业级监控回放体验
前端·javascript·vue·时间轴
岁岁种桃花儿3 小时前
Vue组件第六篇:Vue单文件组件
开发语言·前端·javascript·vue.js
yivifu3 小时前
创建支持交叉链接且鼠标悬停显示注释框的HTML文件
前端·javascript·html
雪芽蓝域zzs17 小时前
vue解构平铺VS对象包裹
前端·javascript·vue.js