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


相关推荐
二十雨辰26 分钟前
歌词滚动效果
前端·css
法医28 分钟前
和文心快码做朋友,让编程像“说话”一样简单
前端·文心快码
前端小巷子31 分钟前
JS 打造「放大镜 + 缩略图」一体组件
前端·javascript·面试
陈随易32 分钟前
适合中国宝宝的AI编程神器,文心快码
前端·后端·node.js
知识分享小能手36 分钟前
React学习教程,从入门到精通,React AJAX 语法知识点与案例详解(18)
前端·javascript·vue.js·学习·react.js·ajax·vue3
UrbanJazzerati1 小时前
掌握 DOM 的基础属性与方法:从操作元素到构建动态效果
前端·面试
hashiqimiya1 小时前
html实现右上角有个图标,鼠标移动到该位置出现手型,点击会弹出登录窗口。
前端·html
古夕2 小时前
前端文件下载的三种方式:a标签、Blob、ArrayBuffer
前端·javascript·vue.js
纯真时光2 小时前
Vue3中pinia状态管理库的使用(Composition API 风格)
前端
万少2 小时前
可可图片编辑 HarmonyOS(5)滤镜效果
前端