ES6 中的 Proxy 全面讲解

目录

[一、什么是 Proxy](#一、什么是 Proxy)

[二、常用的拦截操作(handler traps)](#二、常用的拦截操作(handler traps))

[1. get ------ 拦截对象属性的读取](#1. get —— 拦截对象属性的读取)

[2. set ------ 拦截对象属性的赋值](#2. set —— 拦截对象属性的赋值)

[3. has ------ 拦截 in 操作符](#3. has —— 拦截 in 操作符)

[4. deleteProperty ------ 拦截 delete 操作](#4. deleteProperty —— 拦截 delete 操作)

[5. apply ------ 拦截函数调用](#5. apply —— 拦截函数调用)

[6. construct ------ 拦截 new 操作](#6. construct —— 拦截 new 操作)

[三、Proxy 的应用场景](#三、Proxy 的应用场景)

[四、Proxy 与 Object.defineProperty 的区别](#四、Proxy 与 Object.defineProperty 的区别)


一、什么是 Proxy

Proxy 是 ES6 引入的一个强大功能,意思是"代理"。它可以用来拦截对象的操作,并在操作时进行自定义的逻辑处理。

你可以把 Proxy 理解成:

👉 在 对象外部访问者 之间加了一层"代理层",所有对对象的操作都会先经过 Proxy,从而让我们有机会"改写"这些操作。

语法如下:

javascript 复制代码
let proxy = new Proxy(target, handler);
  • target:要代理的对象(可以是对象、数组、函数等)

  • handler:包含拦截方法的对象,不同的方法对应不同的拦截操作


二、常用的拦截操作(handler traps)

1. get ------ 拦截对象属性的读取

javascript 复制代码
const user = {
  name: "Tom",
  age: 18
};

const proxy = new Proxy(user, {
  get(target, prop) {
    if (prop === "age") {
      return target[prop] + " 岁"; 
    }
    return target[prop];
  }
});

console.log(proxy.name); // Tom
console.log(proxy.age);  // 18 岁

👉 在读取 age 时被拦截,返回了一个自定义的字符串。


2. set ------ 拦截对象属性的赋值

javascript 复制代码
const user = {};

const proxy = new Proxy(user, {
  set(target, prop, value) {
    if (prop === "age") {
      if (typeof value !== "number") {
        throw new TypeError("年龄必须是数字!");
      }
    }
    target[prop] = value;
    return true; // 必须返回 true 表示赋值成功
  }
});

proxy.age = 20; 
console.log(proxy.age); // 20

proxy.age = "abc"; // 报错:年龄必须是数字!

👉 可以在设置属性时做数据校验,非常适合做表单验证。


3. has ------ 拦截 in 操作符

javascript 复制代码
const user = { name: "Tom", password: "123456" };

const proxy = new Proxy(user, {
  has(target, prop) {
    if (prop === "password") {
      return false; // 隐藏 password 属性
    }
    return prop in target;
  }
});

console.log("name" in proxy);     // true
console.log("password" in proxy); // false

👉 可以用来隐藏敏感信息。


4. deleteProperty ------ 拦截 delete 操作

javascript 复制代码
const user = { name: "Tom" };

const proxy = new Proxy(user, {
  deleteProperty(target, prop) {
    if (prop === "name") {
      console.log("name 属性不能被删除!");
      return false;
    }
    return true;
  }
});

delete proxy.name; // name 属性不能被删除!
console.log(proxy.name); // Tom

5. apply ------ 拦截函数调用

javascript 复制代码
function sum(a, b) {
  return a + b;
}

const proxy = new Proxy(sum, {
  apply(target, thisArg, args) {
    console.log("拦截函数调用,参数是:", args);
    return target(...args) * 2; // 返回值改为原函数结果的两倍
  }
});

console.log(proxy(1, 2)); // 6

6. construct ------ 拦截 new 操作

javascript 复制代码
class Person {
  constructor(name) {
    this.name = name;
  }
}

const ProxyPerson = new Proxy(Person, {
  construct(target, args) {
    console.log("正在创建实例,参数:", args);
    return new target(...args);
  }
});

const p = new ProxyPerson("Tom");
// 正在创建实例,参数: [ 'Tom' ]

三、Proxy 的应用场景

  1. 数据验证(如 set 中校验数据类型)

  2. 隐藏属性(如 has、get 中屏蔽敏感数据)

  3. 调试/日志记录(在 get/set 时记录日志)

  4. 自动填充默认值(属性不存在时返回默认值)

  5. 函数增强(apply 中扩展函数功能)

  6. Vue3 响应式实现(Vue3 底层用 Proxy 实现数据劫持)


四、Proxy 与 Object.defineProperty 的区别

在 Vue2 中,响应式是通过 Object.defineProperty 实现的,而 Vue3 改用了 Proxy。

  • Object.defineProperty 只能监听对象的属性,不能监听对象本身

  • Proxy 能直接代理整个对象,不需要对每个属性单独处理

  • Proxy 能监听更多操作(如 indelete函数调用 等)

因此,Proxy 更加灵活、强大,也逐渐成为未来的主流。


相关推荐
excel7 分钟前
Qiankun 子应用生命周期及使用场景解析
前端
weixin_4462608511 分钟前
Django - 让开发变得简单高效的Web框架
前端·数据库·django
ObjectX前端实验室1 小时前
【react18原理探究实践】异步可中断 & 时间分片
前端·react.js
SoaringHeart1 小时前
Flutter进阶:自定义一个 json 转 model 工具
前端·flutter·dart
努力打怪升级1 小时前
Rocky Linux 8 远程管理配置指南(宿主机 VNC + KVM 虚拟机 VNC)
前端·chrome
brzhang2 小时前
AI Agent 干不好活,不是它笨,告诉你一个残忍的现实,是你给他的工具太难用了
前端·后端·架构
brzhang2 小时前
一文说明白为什么现在 AI Agent 都把重点放在上下文工程(context engineering)上?
前端·后端·架构
reembarkation2 小时前
自定义分页控件,只显示当前页码的前后N页
开发语言·前端·javascript
gerrgwg3 小时前
React Hooks入门
前端·javascript·react.js
ObjectX前端实验室3 小时前
【react18原理探究实践】调度机制之注册任务
前端·react.js