ES6如何改变JS内置行为的代理与反射

  

代理(代理)可以拦截并改变JS引擎的底层操作,如数据读取,属性定义,函数构造等一系列操作.ES6通过对这些底层内置对象的代理陷阱和反射函数,让开发者能进一步接近JS引擎的能力。
  

  


  

  

<强>什么是代理和反射呢?
  

  

代理是用来替代另一个对象(目标),JS通过新代理()创建一个目标对象的代理,该代理与该目标对象表面上可以被当作同一个对象来对待。

  

当目标对象上的进行一些特定的底层操作时,代理允许你拦截这些操作并且覆写它,而这原本只是JS引擎的内部能力。

  
  

如果你对些代理,反射的概念比较困惑的话,可以直接看后面的应用示例,最后再重新看这些定义就会更清晰!
  

     

拦截行为使用了一个能够响应特定操作的函数(被称为陷阱),每个代理陷阱对应一个反射(反映)方法。

  

ES6的反射API以反映对象的形式出现,对象每个方法都与对应的陷阱函数同名,并且接收的参数也与之一致。以下是反映对象的一些方法:
  

  

           代理陷阱   覆写的特性   方法                  得到   读取一个属性的值   Reflect.get ()         集   写入一个属性   Reflect.set ()         有   在运算符   Reflect.has ()         deleteProperty   删除运算符   Reflect.deleteProperty ()         getPrototypeOf   Object.getPrototypeOf ()   Reflect.getPrototypeOf ()         isExtensible   Object.isExtensible ()   Reflect.isExtensible ()         defineProperty   Object.defineProperty ()   Reflect.defineProperty         应用   调用一个函数   Reflect.apply ()         构造   使用新调用一个函数   Reflect.construct ()            

  

每个陷阱函数都可以重写JS对象的一个特定内置行为,允许你拦截并修改它。

  

综合来说,想要控制或改变JS的一些底层操作,可以先创建一个代理对象,在这个代理对象上挂载一些陷阱函数,陷阱函数里面有反射方法。通过接下来的应用示例可以更清晰的明白代理的过程。

  


  

  

当你使用代理构造器来创建一个代理时,需要传递两个参数:目标对象(目标)以及一个处理器(处理器),

  

先创建一个仅进行传递的代理如下:

     //目标对象   让目标={};//代理对象   让代理=new代理(目标,{});      proxy.name=澳愫谩?   console.log (proxy.name);//澳愫谩?   console.log (target.name);//澳愫谩?      target.name="世界";   console.log (proxy.name);//笆澜纭?   console.log (target.name);//笆澜?      之前      

上例中的代理代理对象将所有操作直接传递给目标目标对象,代理对象代理自身并没有存储该属性,它只是简单将值传递给目标对象,proxy.name与target.name的属性值总是相等,因为它们都指向target.name。

  

此时代理陷阱的处理器为空对象,当然处理器可以定义了一个或多个陷阱函数。

  

<强> 2.1验证对象属性的存储
  

  

假设你想要创建一个对象,并要求其属性值只能是数的值,这就意味着该对象的每个新增属性
  

  

都要被验证,并且在属性值不为数值类型时应当抛出错误。

  

这时需要使用设陷阱函数来拦截传入的值,该陷阱函数能接受四个参数:

  
      <李> trapTarget:将接收属性的对象(即代理的目标对象)   <李>关键:需要写入的属性的键(字符串类型或符号类型)   <李>值:将被写入属性的值;李   <李>接收机:操作发生的对象(通常是代理对象)   
  

设置陷阱对应的反射方法和默认特性是Reflect.set(),和陷阱函数一样接受这四个参数,并会基于操作是否成功而返回相应的结果:

        让targetObj={};   让proxyObj=新代理(targetObj, {   设置:设置   });/*定义集陷阱函数*/函数集(trapTarget、关键值,接收机){   如果(isNaN(值)){   把新TypeError(“财产”+键+”必须是一个数字。”);   }   返回反映。集(trapTarget、关键值,接收方);   }/*测试*/proxyObj。数=123;   console.log (proxyObj.count);//123   console.log (targetObj.count);//123      proxyObj。anotherName="代理"//TypeError:财产anotherName必须是一个数字。   

ES6如何改变JS内置行为的代理与反射