当前位置: 首页 > Web前端 > JavaScript

为什么vue3选择代理,有什么好处?_1

时间:2023-03-27 00:35:54 JavaScript

请问Object.defineProperty()和proxy的区别?为什么vue3选择代理,有什么好处?proxyProxy对象用于创建一个对象的代理,从而实现对基本操作(如属性查找、赋值、枚举、函数调用等)的拦截和定制。Proxy的用法大家都知道。constp=newProxy(target,handler)分析ECMAScript2017(ECMA-262)的内部实现,可以看到它接收两个参数(target,handler)如果target未定义,则报错并运行ProxyCreate(target,handler)下面是ProxyCreate排除错误处理的实现,核心代码从5开始新建一个空对象p,并设置p对象的内部方法([call]]和[[Construct]]除外)to[9.5指定定义,然后设置p的call和Construct方法,然后设置内部属性[[ProxyTarget]]和[[ProxyHandler]]返回对象p,我们可以用它们拦截什么?对于对象上的大多数操作,JavaScript规范都有一个所谓的“内部方法”,它描述了最低级别的工作方式。比如[[Get]],读取属性的内部方法,[[Set]],写入属性的内部方法等等。这些方法只是在规范中使用,我们不能通过方法名直接调用它们。代理陷阱拦截对这些方法的调用。它们列在代理规范和下表中。对于每一个内部方法,在这个表中都有一个捕手:方法名,可以添加到newProxy的handler参数中来拦截操作:对于大多数对对象的操作,在JavaScript规范,它描述了最低级别的工作方式。比如[[Get]],读取属性的内部方法,[[Set]],写入属性的内部方法等等。这些方法只是在规范中使用,我们不能通过方法名直接调用它们。代理陷阱拦截对这些方法的调用。它们列在代理规范和下表中。对于每一个内部方法,在这个表中都有一个捕手:方法名,可以添加到新Proxy的handler参数中来拦截动作:internalmethodHandlermethodwhenfire[[Get]]getreadproperty[[Set]]setwriteproperty[[HasProperty]]hasinoperator[[Delete]]deletePropertydeleteoperator[[Call]]applyfunctioncall[[Construct]]constructnewoperator[GetPrototypeOf]]getPrototypeOf[Object.getPrototypeOf[SetPrototypeOf]]setPrototypeOf[Object.setPrototypeOf][IsExtensible]]isExtensible[Object.isExtensible[PreventExtensions]]preventExtensions[Object.preventExtensions[DefineOwnProperty]]defineProperty[Object.defineProperty,Object.defineProperties[GetOwnProperty]]getOwnPropertyDescriptor[Object.getOwnPropertyDescriptor.in,Object.keys/values/条目[OwnPropertyKeys]]ownKeys[Object.getOwnPropertyNames,Object.getOwnPropertySymbols,for..in,Object.keys/values/entriesReflectReflect是一个内置对象,可以简化Proxy的创建。上面提到的内部方法,如[[Get]]和[[Set]]等,只是规范的,不能直接调用。反射对象使得调用这些内部方法成为可能。它的方法是内部方法的最小包装器。特别是,Reflect允许我们将运算符(new、delete等)作为函数(Reflect.construct、Reflect.deleteProperty等)来调用。这是一个有趣的特性,但这里还有更重要的一点。对于每个可以被Proxy捕获的内部方法,在Reflect中都有一个对应的方法,其名称和参数与Proxy捕获器相同。因此,我们可以使用Reflect将操作转发给原始对象。我们可以重写捕手使其更短:get(target,prop,receiver){returnReflect.get(...arguments);Reflect调用的名称与捕手完全相同,并且接受相同的参数。它们是专门以这种方式设计的。所以returnReflect...提供了一种安全的方式来轻松转发操作并确保我们不会忘记它的任何内容。proxy的局限性1.不能代理internalslots许多内置对象,如Map、Set、Date、Promise等,都使用所谓的“internalslots”。例如:letmap=newMap();letproxy=newProxy(map,{});proxy.set('test',1);//报错解决方法设置目标对象后getReturn时绑定get要返回的值letmap=newMap();letproxy=newProxy(map,{get(target,prop,receiver){letvalue=Reflect.get(...arguments);returntypeofvalue=='function'?value.bind(target):value;}});proxy.set('test',1);alert(proxy.get('test'));//1(worked!)2.private字段也同上3.peoxy!=target这个好理解,代理对象和目标对象不是===总结代理是对象的包装器,将代理上的操作转发给对象,并且可以选择捕获其中的一些操作。它可以包装任何类型的对象,包括类和函数。语法是:letproxy=newProxy(target,{/*trap*/});...然后,我们应该到处使用代理而不是目标。代理没有自己的属性或方法。如果提供了陷阱,它会捕获操作,否则它会被转发给目标对象。我们可以捕获get、set、deleteProperty等操作函数调用(applycapture)new操作(constructcapture)Reflect是为了补充Proxy而设计的。对于任何Proxy捕手,都会调用具有相同参数的Reflect。我们应该使用它们将调用转发给目标对象。Proxy的局限性不能代理内部对象的内部槽不能代理私有字段Proxy对象和目标对象不相等返回这个对象。语法Object.defineProperties(obj,props)描述了对象中当前存在的属性描述符。主要有两种形式:数据(属性)描述符和访问描述符(访问器属性)。数据描述符是一个具有值的属性,它可能是可写的,也可能是不可写的。访问器描述符是由getter和setter函数描述的属性。描述符只能是这两者之一;不可能两者兼而有之。参考视频解释:输入学习属性描述符值——值可写——如果为真,则该值可修改,否则为只读。enumerable——如果为真,将在循环中枚举,否则不枚举。可配置——如果为真,则可以删除此属性并可以修改这些属性,否则不能。accessor属性get-一个没有参数的函数,在读取属性时起作用,set-一个有一个参数的函数,在设置属性时调用,可枚举-与数据属性相同,可配置-与数据属性相同。先回答第一个问题,Object.defineProperty()和proxy有什么区别?Object.definePropertyProxy添加/修改对象的属性,定义其描述,返回对象的代理目标对象,拦截其操作。返回的代理对象有两种类型的数据描述符和访问器描述符来拦截13个操作。能否代理正则对象可以代理任何对象(函数、数组、类)-不能代理内部对象的内部槽回答第二个问题vue3为什么要选择代理,有什么好处?可以代理任何对象,包括数组和函数。与Object.defineProperty()相比,对象具有更多的基本语义操作(获取、设置、删除...)。无需遍历对象然后使用Object.defineProperty()。Proxy可以代理对象内的所有属性。Object.defineProperty()只能劫持对象的属性(给对象添加属性vue检测不到)