ES6 中的 Proxy 全面讲解

ES6中Proxy全面解析

目录

一、什么是 Proxy

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

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

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

3. has —— 拦截 in 操作符

4. deleteProperty —— 拦截 delete 操作

5. apply —— 拦截函数调用

6. construct —— 拦截 new 操作

三、Proxy 的应用场景

四、Proxy 与 Object.defineProperty 的区别


一、什么是 Proxy

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

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

语法如下:

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

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


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

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

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 —— 拦截对象属性的赋值

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 操作符

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 操作

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 —— 拦截函数调用

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 操作

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


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值