Vue3.0 开始用 Proxy 代替 Object.defineProperty了,这篇文章结合实例教你如何使用Proxy
本篇文章同时收录【前端知识点】中,链接直达
JavaScript 中的 Proxy 是什么?能干什么?Vue3.0 开始为什么用 Proxy 代替 Object.definePropertyProxy 是什么解释参考MDN,链接直达
const p = new Proxy(target, handler)
target: 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)handler: 对该代理对象的各种操作行为处理(为空对象的情况下,基本可以理解为是对第一个参数做的一次浅拷贝)target 就是你想要代理的对象;而 handler 是一个函数对象,其中定义了所有你想替 target 代为管理的操作对象,包含了:
handler.has(target, prop): in 操作符的捕捉器,拦截HasProperty操作handler.get(target, prop): 属性读取操作的捕捉器handler.set(target, prop, value): 属性设置操作的捕捉器handler.apply(target, object, args): 函数调用操作的捕捉器,拦截函数的调用、call和apply操作handler.getPrototypeOf(): Object.getPrototypeOf 方法的捕捉器handler.setPrototypeOf(): Object.setPrototypeOf 方法的捕捉器handler.isExtensible(): Object.isExtensible 方法的捕捉器handler.preventExtensions(): Object.preventExtensions 方法的捕捉器handler.getOwnPropertyDescriptor(): Object.getOwnPropertyDescriptor 方法的捕捉器handler.defineProperty(): Object.defineProperty 方法的捕捉器handler.deleteProperty(): delete 操作符的捕捉器handler.ownKeys(): Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器handler.construct(): new 操作符的捕捉器不可配置 || 不可写,则该属性不可被代理,通过 Proxy 访问该属性会报错。* 标记的trap为本文都要涉及到的Proxy 能干什么?
undefined has trap 来掩盖这个属性的存在
has 方法拦截的是 hasProperty 操作,不是 hasOwnProperty,所以 has...in 方法不判断一个属性是自身属性还是继承的属性
注意: has...in 可以拦截到,for...in 拦截不到
阻止其他人删除属性,想让调用方法的人知道该方法已经被废弃,或是想阻止其他人修改属性
Proxy 代理起作用,必须针对 Proxy 的实例进行操作,而不是针对目标对象进行操作

针对那些重度依赖资源,执行缓慢或是频繁使用的方法或接口,统计它们的使用或是性能
可以记录各种各样的信息而不用修改应用程序的代码或是阻塞代码执行。并且只需要在这些代码的基础上稍事修改就可以记录特性函数的执行性能

以上例子就是一个监听函数执行的代理,可以将其进行扩展为打点函数
这里面 Proxy 的 trap 为什么使用 get 而不是 apply ? 答案
Proxy 进行封装让构造函数也能够直接进行函数调用
需要解决的几个问题
xxx.xxx.xxx...无论 undefined 出现在哪里都不能报错Proxy 的 get() 传入的参数必须是对象传统方式深层取值繁琐,利用Proxy可以简化不必要代码

但是当 target[prop] 是 undefined 的时候,Proxy get()的入参变成了 undefined,但 Proxy 第一个入参必须为对象
需要对 obj 为 undefined 的时候进行特殊处理,为了能够深层取值,所以使用一个空函数进行设置拦截,利用 apply trap 进行处理

我们理想中的应该是,如果属性为 undefined 就返回 undefined,但仍要支持访问下级属性,而不是抛出错误
顺着这个思路来的话,很明显当属性为 undefined 的时候也需要用 Proxy 进行特殊处理
所以我们需要一个具有下面特性的 get() 方法
getData(undefined)() === undefined; // true
getData(undefined).xxx.yyy.zzz(); // undefined
get(undefined).xxx 是否为正确的值,因为想获取值必须要执行才能拿到undefined 后面访问的属性都默认为 undefined 就好了,所以我们需要一个代理了 undefined 后的返回对象undefined 的时候,停止执行
Proxy 本质上属于元编程非破坏性数据劫持,在原对象的基础上进行了功能的衍生而又不影响原对象,符合松耦合高内聚的设计理念Object.defineProperty 通过为属性设置 getter/setter 能够完成数据的响应式,但是它并不算是实现数据的响应式的完美方案,某些情况下需要对其进行修补或者hack,这也是它的缺陷,主要表现在两个方面:

Vue.set() 重新设置添加属性的响应式

push/pop/shift/unshift/splice/sort/reverse 这七个方法,其他数组方法及数组的使用则无法检测到,也无法监听数组索引的变化和长度的变更
Proxy 的性能比 Promise 还差Proxy 作为新标准,从长远来看,JS 引擎会继续优化 ProxyVue 3.0 中放弃了对于IE的支持(以为 Vue 3.0 中会对不兼容的浏览器进行向下兼容,但是经过查看资料和源码发现尤大压根没做兼容)Proxy 所有拦截方法的 Polyfill 方案,有一个 google 编写的 proxy-polyfill 也只支持了 get/set/apply/construct 四种拦截Decorator,相当于设计模式中的装饰器模式。Proxy 和 Decorator 的使用场景,可以概括为:Proxy 的核心作用是控制外界对被代理者内部的访问,Decorator 的核心作用是增强被装饰者的功能。原文:https://www.cnblogs.com/programmerzhang/p/14031921.html