❣ 你都用了这么久的vue3了,但是你真的懂Proxy吗?

阿轩的BUG
文章191
评论56
标签101
站点日志
作者总数:1位
置顶文章:0篇
标签总数:101条
文章总数:196篇
评论总数:56条
微语总数:201条
运行天数:2317天
最近更新:2026-07-28
文章标签
最新评论
Sherlock
2025-08-21
不是应该打包成apk文件吗,怎么突然就运行编译了,下一步呢
老金er
2025-05-25
人生设计非常必要,在信息化发达的今天,周围大部分人依然只能过着人生工程模式生活,长时间生活洗礼后,尽管“人生工程”已经不再适合很多人,他们也无法做出任何改变,人生设计给我们提供了新的思路,值得尝试
赏帮赚
2025-05-25
职场太多的尔虞我诈
三笑
2024-08-16
emlog6.0.1可以升级支持吗?
pony
2024-07-08
这篇文章提供了一种新的人生规划方法——"人生设计",它借鉴了产品设计的理念,鼓励人们以创造性和探索性的方式思考和规划自己的生活。以下是对这篇文章的几个评价维度: 创新性:将产品设计的理念应用于人生规划是一个新颖的视角,为人们提供了一种跳出传统生活轨迹,探索个性化生活路径的方法。 实用性:文章不仅提出了理念,还详细介绍了具体的实施步骤,包括自我评估、制定计划、原型设计和实践选择等,具有很强的操作性。 启发性:通过强调好奇心、不断尝试、重新定义问题等心态,文章鼓励人们打破常规,勇于探索未知,这对于激发个人潜能和创造力具有积极作用。 适应性:"人生设计"理念适用于不同人生阶段和不同背景的人,无论是希望从头开始的人,还是已经取得一定成就但希望探索新方向的人,都可以从中获得启发。 情感共鸣:文章对许多人对传统生活轨迹的不满和对改变的渴望进行了深刻的洞察,能够引起读者的共鸣。 可持续性:人生设计强调的是一个持续迭代和试错的过程,这与现实生活的发展规律相吻合,有助于人们在不断变化的环境中做出适应性调整。 教育意义:作为一种人生规划方法,"人生设计"可以作为教育的一部分,帮助年轻人更早地学会自我探索和规划,为未来的生活和职业发展打下基础。 局限性:尽管"人生设计"提供了一种新的思考框架,但它可能需要个人具备一定的自我认知和反思能力,对于一些缺乏自我探索经验的人来说,可能需要额外的指导和支持。 总体来说,这篇文章提供了一种有价值的人生规划方法,对于那些渴望改变、寻求个性化生活的人来说,是一种有益的参考和指导。
首页实用干货 🌋

Proxy是ES6引入的一个新特性,它允许你创建一个代理对象,用于拦截对目标对象的访问。通过使用Proxy,你可以拦截目标对象上的各种操作,比如属性访问、属性赋值、函数调用等,并在这些操作发生时执行自定义的逻辑。

在Vue 3中,Proxy被用于劫持组件实例,以实现响应式数据的跟踪和更新。当你在Vue组件中声明一个响应式的数据属性时,Vue内部会使用Proxy来追踪该属性的变化。这样,当属性的值发生变化时,Vue能够自动检测到这个变化,并更新相关的视图。

在使用Vue 3时,你可能会直接或间接地接触到Proxy对象,尤其是在处理响应式数据时。然而,对于大多数Vue开发者来说,并不需要深入理解Proxy的内部工作原理,因为Vue已经为你处理了大部分的细节。

但是作为一个优秀的前端开发者,如果你对JavaScript的高级特性和底层实现都不感兴趣,这和咸鱼有什么区别。

目录:

  1. Proxy简介
  2. Proxy的基本语法
  3. get拦截器:捕获属性的获取操作
  4. set拦截器:捕获属性的设置操作
  5. has拦截器:捕获属性存在性的查询操作
  6. apply拦截器:捕获函数的调用操作
  7. getOwnPropertyDescriptor拦截器:捕获属性描述符的获取操作
  8. defineProperty拦截器:捕获属性的定义操作
  9. deleteProperty拦截器:捕获属性的删除操作
  10. Proxy的陷阱(Trap)
    • getPrototypeOf
    • setPrototypeOf
    • isExtensible
    • preventExtensions
    • getOwnPropertyNames
    • ownKeys
    • construct
  11. Proxy的应用场景
    • 数据绑定和响应式
    • 验证和过滤
    • 缓存和延迟加载
    • 日志记录和错误处理
  12. Proxy的限制和注意事项

1. Proxy简介

JavaScript的Proxy是一种元编程特性,它允许我们拦截并修改对象的基本操作。通过在对象和其目标之间插入一个代理层,Proxy可以截获对目标对象的各种操作,包括属性的读取、写入、删除以及函数的调用等。通过定义自定义的拦截器方法,我们可以控制这些操作的行为,实现各种高级功能。

3. Proxy的基本语法

Proxy的基本语法非常简单,使用new Proxy(target, handler)的形式创建一个Proxy对象。其中,target是目标对象,handler是一个包含拦截器方法的对象。拦截器方法会在对目标对象进行操作时被调用,允许我们拦截并修改这些操作的行为。

3. get拦截器:

捕获属性的获取操作 get拦截器用于拦截对目标对象属性的获取操作。它接收两个参数:target(目标对象),property(属性名)。在拦截器中,我们可以根据需要修改或处理属性的获取行为。

const target = {
  name: 'Alice',
  age: 25
};

const handler = {
  get(target, property) {
    console.log(`Getting property: ${property}`);
    return target[property];
  }
};

const proxy = new Proxy(target, handler);

console.log(proxy.name); // 输出: Getting property: name    Alice
console.log(proxy.age); // 输出: Getting property: age    25

在上述示例中,我们定义了一个目标对象target,包含了nameage两个属性。通过创建一个Proxy对象proxy,并在handler对象中实现了get拦截器方法,我们可以捕获对目标对象属性的获取操作。在拦截器方法中,我们输出了被获取的属性名,并返回了目标对象中对应的属性值。

4. set拦截器

捕获属性的设置操作 set拦截器用于拦截对目标对象属性的设置操作。它接收三个参数:target(目标对象),property(属性名),value(属性值)。在拦截器中,我们可以根据需要修改或处理属性的设置行为。

const target = {
  name: 'Alice',
  age: 25
};

const handler = {
  set(target, property, value) {
    console.log(`Setting property: ${property} = ${value}`);
    target[property] = value;
    return true;
  }
};

const proxy = new Proxy(target, handler);

proxy.name = 'Bob'; // 输出: Setting property: name = Bob
proxy.age = 30; // 输出: Setting property: age = 30

console.log(proxy.name); // 输出: Bob
console.log(proxy.age); // 输出: 30

在上述示例中,我们通过创建Proxy对象并实现set拦截器方法,捕获了对目标对象属性的设置操作。在拦截器方法中,我们输出了被设置的属性名和值,并将值赋给目标对象的对应属性。

5. has拦截器

捕获属性存在性的查询操作 has拦截器用于拦截对属性存在性的查询操作,例如使用in运算符或Reflect.has()方法。它接收两个参数:target(目标对象),property(属性名)。在拦截器中,我们可以自定义属性的存在性判断逻辑。

const target = {
  name: 'Alice',
  age: 25
};

const handler = {
  has(target, property) {
    console.log(`Checking property existence: ${property}`);
    return property in target;
  }
};

const proxy = new Proxy(target, handler);

console.log('name' in proxy); // 输出: Checking property existence: name    true
console.log('gender' in proxy); // 输出: Checking property existence: gender    false

在上述示例中,我们创建了一个Proxy对象,并实现了has拦截器方法。在拦截器方法中,我们输出了查询的属性名,并通过判断属性是否存在于目标对象中来返回相应的结果。

6. apply拦截器

捕获函数的调用操作 apply拦截器用于拦截对函数的调用操作。它接收三个参数:target(目标对象),thisArg(函数的上下文对象),argumentsList(函数的参数列表)。在拦截器中,我们可以自定义函数的调用行为。

const target = function(a, b) {
        return a + b;
};
const handler = {
        apply(target, thisArg, argumentsList) {
                console.log('Calling function');
                return target.apply(thisArg, argumentsList);
        }
};
const proxy = new Proxy(target, handler);
console.log(proxy(2, 3)); // 输出: Calling function 5

在上述示例中,我们创建了一个目标函数target,并通过创建Proxy对象并实现apply拦截器方法,捕获了对函数的调用操作。在拦截器方法中,我们输出了调用函数的信息,并使用apply方法将调用转发给目标函数,并返回结果

7. getOwnPropertyDescriptor拦截器

捕获属性描述符的获取操作 getOwnPropertyDescriptor拦截器用于拦截对属性描述符的获取操作,例如使用Object.getOwnPropertyDescriptor()方法。它接收两个参数:target(目标对象),property(属性名)。在拦截器中,我们可以自定义属性描述符的获取行为。

    const target = {
      name: 'Alice',
      age: 25
    };

    const handler = {
      getOwnPropertyDescriptor(target, property) {
        console.log(`Getting property descriptor: ${property}`);
        return Object.getOwnPropertyDescriptor(target, property);
      }
    };

    const proxy = new Proxy(target, handler);

    console.log(Object.getOwnPropertyDescriptor(proxy, 'name'));
    // 输出: Getting property descriptor: name    { value: 'Alice', writable: true, enumerable: true, configurable: true }

    console.log(Object.getOwnPropertyDescriptor(proxy, 'age'));
    // 输出: Getting property descriptor: age    { value: 25, writable: true, enumerable: true, configurable: true }

在上述示例中,我们创建了一个Proxy对象,并实现了getOwnPropertyDescriptor拦截器方法。在拦截器方法中,我们输出了获取属性描述符的属性名,并通过Object.getOwnPropertyDescriptor()方法获取目标对象的属性描述符,并返回结果

8. defineProperty拦截器

捕获属性的定义操作 defineProperty拦截器用于拦截对属性的定义操作,例如使用Object.defineProperty()方法。它接收三个参数:target(目标对象),property(属性名),descriptor(属性描述符)。在拦截器中,我们可以自定义属性的定义行为。

const target = {};

const handler = {
  defineProperty(target, property, descriptor) {
    console.log(`Defining property: ${property}`);
    return Object.defineProperty(target, property, descriptor);
  }
};

const proxy = new Proxy(target, handler);

Object.defineProperty(proxy, 'name', { value: 'Alice' });
// 输出: Defining property: name

Object.defineProperty(proxy, 'age', { value: 25 });
// 输出: Defining property: age

console.log(proxy.name); // 输出: Alice 
console.log(proxy.age); // 输出: 25

在上述示例中,我们创建了一个Proxy对象,并实现了defineProperty拦截器方法。在拦截器方法中,我们输出了属性的定义信息,并使用Object.defineProperty()方法将属性定义应用到目标对象上。

9. deleteProperty拦截器

捕获属性的删除操作 deleteProperty拦截器用于拦截对属性的删除操作,例如使用delete关键字。它接收两个参数:target(目标对象),property(属性名)。在拦截器中,我们可以自定义属性的删除行为。

const target = {
 name: 'Alice',
 age: 25
};

const handler = {
 deleteProperty(target, property) {
   console.log(`Deleting property: ${property}`);
   return delete target[property];
 }
};

const proxy = new Proxy(target, handler);

delete proxy.name; // 输出: Deleting property: name

console.log(proxy.name); // 输出: undefined
console.log(proxy.age); // 输出: 25

在上述示例中,我们创建了一个Proxy对象,并实现了deleteProperty拦截器方法。在拦截器方法中,我们输出了被删除的属性名,并使用delete关键字将属性从目标对象中删除。

10. Proxy的陷阱(Trap)

除了上述介绍的常用拦截器方法,Proxy还提供了一些陷阱(Trap)方法,用于拦截更细粒度的操作。这些陷阱方法包括getPrototypeOfsetPrototypeOfisExtensiblepreventExtensionsgetOwnPropertyNamesownKeysconstruct。它们提供了更高级的对象操作和元编程能力。

11. Proxy的应用场景

Proxy的强大功能使其在许多应用场景中发挥着重要作用。以下是一些常见的应用场景:

  • 数据绑定和响应式:通过拦截对象属性的获取和设置操作,我们可以实现数据绑定和响应式系统,使数据的变化能够自动更新视图。
  • 验证和过滤:通过拦截属性的设置操作,我们可以实现数据验证和过滤,确保属性值的有效性和一致性。
  • 缓存和延迟加载:通过拦截函数的调用操作,我们可以实现缓存和延迟加载的功能,提高性能和资源利用率。
  • 日志记录和错误处理:通过拦截各种操作,我们可以实现日志记录和错误处理的功能,帮助调试和排查问题。

12. Proxy的限制和注意事项

在使用Proxy时,需要注意以下限制和注意事项:

  • Proxy无法拦截内部方法;
  • 原生对象的扩展需要谨慎使用;
  • 性能开销的考虑;
  • Proxy无法取消拦截器的影响。

总结

JavaScript的Proxy是一个功能强大的工具,它提供了拦截和修改对象操作的能力。通过定义自定义的拦截器方法,我们可以自定义对象的行为,实现各种高级功能。无论是数据绑定和响应式系统,还是验证和过滤、缓存和延迟加载,Proxy都可以应用于各种场景中。然而,我们也需要注意Proxy的一些限制和注意事项,以确保正确使用和避免性能问题。掌握Proxy的基本语法和各个拦截器方法的使用,将使我们能够更好地利用Proxy的强大功能,提升JavaScript开发的灵活性和效率。

上一篇
🌈 Vue3优雅的监听localStorage变化
下一篇
💭 聊聊本地缓存和分布式缓存