news 2026/2/26 0:23:33

什么是proxy

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
什么是proxy

在前端开发中,Proxy是 ES6 引入的一个高级特性,用于拦截和自定义对象的基本操作(如属性访问、赋值、枚举、函数调用等)。它为开发者提供了元编程能力,是实现响应式系统、数据校验、访问控制等功能的核心技术。

一、基本概念

定义
Proxy是一个构造函数,用于创建一个对象的代理,从而可以对该对象的基本操作进行拦截和自定义处理。
语法

const proxy = new Proxy(target, handler);
  • target:需要被代理的对象。
  • handler:包含拦截方法的对象,用于定义如何处理目标对象的操作。
    二、核心拦截方法(常用)
    1.get(target, property, receiver)

    作用:拦截对象属性的读取操作。
    示例

    const person = { name: 'Doubao', age: 25 }; const proxy = new Proxy(person, { get(target, prop) { // 拦截属性读取,添加默认值 return prop in target ? target[prop] : '未知属性'; } }); console.log(proxy.name); // 输出: Doubao console.log(proxy.gender); // 输出: 未知属性
    2.set(target, property, value, receiver)

    作用:拦截对象属性的赋值操作。
    示例

    const validator = { set(target, prop, value) { // 拦截属性赋值,添加校验逻辑 if (prop === 'age') { if (typeof value !== 'number' || value < 0) { throw new Error('年龄必须为正整数'); } } target[prop] = value; return true; // 必须返回 true 表示赋值成功 } }; const person = new Proxy({}, validator); person.age = 25; // 正常赋值 person.age = -5; // 抛出错误
    3.has(target, property)

    作用:拦截in操作符。
    示例

    const handler = { has(target, prop) { // 隐藏以 _ 开头的私有属性 return prop[0] !== '_' && prop in target; } }; const obj = { name: 'Doubao', _secret: 'xxx' }; const proxy = new Proxy(obj, handler); console.log('name' in proxy); // 输出: true console.log('_secret' in proxy); // 输出: false
    4.deleteProperty(target, property)

    作用:拦截delete操作符。
    示例

    const handler = { deleteProperty(target, prop) { // 禁止删除以 _ 开头的私有属性 if (prop[0] === '_') { throw new Error('不能删除私有属性'); } delete target[prop]; return true; } }; const obj = { name: 'Doubao', _secret: 'xxx' }; const proxy = new Proxy(obj, handler); delete proxy.name; // 正常删除 delete proxy._secret; // 抛出错误
    三、应用场景
    1.响应式系统(如 Vue 3)

    Proxy 是 Vue 3 实现响应式数据的核心技术,相比 Vue 2 的Object.defineProperty,它能拦截更多操作,包括新增属性、删除属性等。
    示例

    function reactive(target) { return new Proxy(target, { get(target, prop) { // 收集依赖 track(target, prop); return target[prop]; }, set(target, prop, value) { target[prop] = value; // 触发更新 trigger(target, prop); return true; } }); } const state = reactive({ count: 0 }); // 当 state.count 变化时,自动触发更新
    2.数据校验与格式化

    在赋值时自动校验数据类型或格式。
    示例

    const user = new Proxy({}, { set(target, prop, value) { if (prop === 'email') { const isValid = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/.test(value); if (!isValid) { throw new Error('邮箱格式不正确'); } } target[prop] = value; return true; } }); user.email = 'invalid'; // 抛出错误 user.email = 'valid@example.com'; // 正常赋值
    3.访问控制与私有属性

    通过拦截gethas隐藏内部属性。
    示例

    const privateData = new WeakMap(); class User { constructor(name, age) { privateData.set(this, { name, age }); } get publicInfo() { return new Proxy(privateData.get(this), { get(target, prop) { if (prop === 'age') { return '保密'; // 隐藏真实年龄 } return target[prop]; } }); } } const user = new User('Doubao', 25); console.log(user.publicInfo.name); // 输出: Doubao console.log(user.publicInfo.age); // 输出: 保密
    4.函数参数增强

    拦截函数调用,添加参数校验或日志记录。
    示例

    function logFunction(fn) { return new Proxy(fn, { apply(target, thisArg, args) { console.log(`调用函数 ${target.name},参数:`, args); const result = target.apply(thisArg, args); console.log(`函数返回:`, result); return result; } }); } const add = (a, b) => a + b; const loggedAdd = logFunction(add); loggedAdd(3, 5); // 输出: // 调用函数 add,参数: [3, 5] // 函数返回: 8

    四、Proxy 与 Object.defineProperty 的对比

    五、注意事项

    兼容性:
    Proxy 是 ES6 特性,不支持 IE 浏览器,需通过 Babel 等工具编译或提供降级方案。

    内存管理:
    Proxy 对象会保持对目标对象的引用,可能导致内存泄漏,需注意适时释放。

    递归代理:
    对于嵌套对象,需递归创建 Proxy 才能实现深层拦截。

    Reflect 对象:
    推荐结合 Reflect 对象使用,以保持操作的默认行为:

    const proxy = new Proxy(target, { get(target, prop, receiver) { return Reflect.get(target, prop, receiver); } });

    通过合理使用 Proxy,开发者可以实现更灵活、高效的元编程,提升代码的可维护性和健壮性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/18 2:16:09

FPGA应用开发和仿真【3.6】

7.8 PID控制器 PID控制器广泛用于控制系统,控制系统中的数字控制部分也是数字信号处理系统的一种。典型的数字PID控制器如图7-63所示,它由前向欧拉法转换连续时间PID控制器而来,其P、I、D三个参数,分别为比例、积分、微分系数,而N用于配置微分单元中滤波器的极点,将有助…

作者头像 李华
网站建设 2026/2/19 17:53:12

四川西昌电器门店:30年本地老店,5大优势让你买电器不踩坑!

【四川西昌京东家电】哪家好&#xff1a;专业深度测评开篇&#xff1a;定下基调随着西昌市民对家电品质与服务需求的提升&#xff0c;选择一家靠谱的家电门店成为关键。本次测评聚焦四川西昌家电市场&#xff0c;旨在通过客观数据与真实体验&#xff0c;为消费者提供权威选购参…

作者头像 李华
网站建设 2026/2/19 1:44:29

python 学习笔记(文件和目录操作)

创建目录 os.makedirs可以递归的创建目录结构。 import os os.makedirs(tmp/python/test,exist_okTrue) #exit_ok True指定了&#xff0c;如果某个要创建的目录已经存在&#xff0c;也不报错删除文件或目录 os.remove 可以删除一个文件 os.remove(test.py)**shutil.rmtree()**…

作者头像 李华
网站建设 2026/2/25 13:04:50

实验一 安全威胁与攻击实验

一、实验目的安全威胁与攻击实验与理论教学第一章信息安全概论相对应。本实验在学生完成MAC地址欺骗攻击与防御实验、OSPF路由项欺骗攻击和防御实验的基础上&#xff0c;使学生能够理解威胁、攻击、资产的关系&#xff0c;并理解基本安全设计原则的重要性。具体如下&#xff1a…

作者头像 李华
网站建设 2026/2/20 22:02:59

二十一、pinctrl子系统

前言 前面我们写的GPIO驱动程序都是自己在驱动里面定义好gpio引脚需要用到的寄存器&#xff0c;然后在驱动程序里面直接去配置这些寄存器。Linux是一个成熟的&#xff0c;跨平台的通用操作系统&#xff0c;对于配置引脚这样的最基本的功能&#xff0c;是已经有一套现成的框架可…

作者头像 李华
网站建设 2026/2/25 6:38:25

Java Web 社区医院信息平台系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展&#xff0c;传统社区医院的管理模式已难以满足现代医疗服务的需求。社区医院在日常运营中涉及患者信息管理、医生排班、药品库存、预约挂号等多方面业务&#xff0c;传统的手工记录或单机系统存在效率低下、数据易丢失、信息共享困难等问题。为了提…

作者头像 李华