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

JavaScript的Proxy_0

时间:2023-03-28 19:51:07 HTML

代理基础ES6增加了代理和反射,为开发者提供拦截和嵌入额外行为到基本操作的能力。可以定义一个与目标对象关联的代理对象,代理对象抽象出目标对象来使用。在这些操作影响到目标对象之前,可以在代理对象中控制对目标对象的跟踪操作。创建一个空代理。最简单的代理是空代理。向目标对象传播障碍物。代理是使用Proxy构造函数创建的,它接受两个参数:一个目标对象和一个处理程序对象。consttarget={name:"hui"}consthandler={}constproxy=newProxy(target,handler)//下面对代理对象的所有操作都会作用于目标对象console.log(proxy.name)//huiproxy.age=24console.log(target.age)//24console.log(proxy.age)//24注意:Proxy.prototype未定义,因此不能使用instanceof运算符;使用严格相等(===)可以区分代理对象和目标对象console.log(proxyinstanceofProxy);//TypeErrorcatcher捕获器是处理程序对象中定义的基本操作的拦截器。每个处理程序对象可以定义零个或多个捕手,每个捕手对应一个基本操作,可以直接或间接地在代理对象上调用。在这些操作传播到目标对象之前,代理可以通过调用捕捉器函数来拦截和修改相应的行为。定义捕获器下面的例子中定义了一个get捕获器,当通过代理对象执行get()操作时,会触发该get捕获器。只有在代理对象上执行这些操作才会触发捕获器,直接在目标对象上执行这些操作仍会产生正常行为。consttarget={name:"hui"}consthandler={get(){return"proxyhandler"}}constproxy=newProxy(target,handler)console.log(proxy.name)//proxyhandlers捕获参数All使用ReflectionAPI的捕获可以访问参数,基于这些参数可以重建捕获方法的原始行为。比如上面提到的getcatcher,会接收到目标对象、要查询的属性和代理对象三个参数consttarget={name:"hui"}consthandler={get(target,property,proxy){//returntarget[property]}}constproxy=newProxy(target,handler)console.log(proxy.name)//hui所有捕获器都可以根据自己的参数重构原来的操作,但是有些捕获器的行为更复杂,我们可以使用捕获器对应的ReflectAPI方法。这些方法与捕获器拦截的方法具有相同的名称和函数签名,并且与被拦截的方法具有相同的行为。因此,反射API可以非常实用。我想定义代理对象如下,handler)console.log(proxy.name)//huizhongcatcherinvariantcatcherhandler的行为必须遵循catcherinvariant。捕手不变量因方法而异,但通常放置在捕手定义似乎表现得太多的地方。例如,如果目标对象上有一个不可配置不可写的数据属性,如果捕获器返回一个与修改后的属性不同的值,就会抛出错误consttarget={}Object.defineProperty(target,'name',{configurable:false,writable:false,value:'hui'})consthandler={get(){return“proxyhandler”}}constproxy=newProxy(target,handler)console.log(proxy.name)//TypeErrorRevocableProxies对于使用newProxy创建的普通代理,这种关联在代理对象的整个生命周期中持续存在。Proxy暴露了revocable()方法,支持撤销代理对象与目标对象的关联。撤销代理的操作是不可逆的。另外,撤销函数(revoke)是幂等的,无论调用多少次,结果都是一样的。撤销代理后,再次调用代理会抛出TypeError错误,处理程序);console.log(proxy.foo)revoke()revoke()//revoke方法是幂等的。结果和多次调用一样console.log(proxy.foo)//TypeError撤销代理后,再次调用代理会抛出错误实用反射API反射API不限于捕获处理程序,大部分反射API在Object类型上都有相应的方法,反射方法适用于细粒度的对象控制和操作。状态标志许多反射方法返回一个布尔值,称为状态标志,指示图形执行的操作是否成功。您可以使用状态标志来重构抛出错误的代码//初始代码consttarget={}try{Object.defineProperty(target,'name',{value:'hui'})console.log('success')}catch(err){console.log(err)}//使用反射重构上面的代码if(Reflect.defineProperty(target,'name',{value:'hui'})){console.log('success')}else{console.log('failed')}以下方法将提供状态标记AlternativeoperatorReflect.get():可以替换对象属性访问运算符Reflect.set():可以替换复制运算符Reflect.has():可以替换inoperator或with()Reflect.deleteProperty():可以替换deleteoperatorReflect.construct():它可以替换newoperator以安全地应用函数。通过apply方法调用函数时,被调用函数也可以定义自己的apply方法。为了避免这个问题,可以在Functionapply方法的原型上调用函数Function.property.apply.call(myFunc,thisVal,args)上面冗长的代码可以通过Reflect.apply来避免Reflect.apply(myFunc,thisVal,参数)