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 更加灵活、强大,也逐渐成为未来的主流。


相关推荐
言德斐5 小时前
Python Web框架深度对比:Django vs Flask vs FastAPI(含优缺点与选型策略)
前端·python·django
疯狂的沙粒5 小时前
前端开发【工具函数】基于dayjs 封装的DateUtils工具函数,可以直接拿着使用
前端·javascript·vue.js·1024程序员节
jingling5555 小时前
CSS进阶 | 不用一行JS!用纯CSS打造会动的现代化单页应用(3D翻转卡片)
前端·javascript·css
温宇飞7 小时前
浏览器路由系统的一种实践
前端
老前端的功夫7 小时前
Vue 插槽深度解析:从基础到高级架构设计
前端
pre_lee7 小时前
vue2响应式原理
前端
小奶包他干奶奶7 小时前
如何使用vscode和express开发node.js
前端·node.js
庞囧7 小时前
通俗易懂讲 React 原理-第二集:Fiber
前端
beckyye7 小时前
给web增加简单的ai对话功能
前端·ai·通义千问·qwen