JS. Proxy Dificultades para conocer

Este artículo será de interés para aquellos que usan Proxy para reactividad o reflexión.
Conocemos bien el comportamiento de los métodos JS si simplemente los usamos dentro de un objeto.
Si un método se pasa a través de una propiedad a otro objeto, entonces funciona con esto, que se define en el marco de otro objeto.

let obj1={prop1:'HEllo',method1(){console.log(this);}} let obj2={method2:obj1.method1}; obj2.method2(); 

Esto debe entenderse claramente cuando se usa Proxy.

 class MyProxy{ constructor(target){ return new Proxy(target,this); } get(target,prop){ console.log(target,prop); //Label1 return target[prop]; } } class PrimitiveType { constructor(target,prop) { this.target=target; this.prop=prop; } get(){ console.log(this);// Label2 return this.target[this.prop]; } } prim=new PrimitiveType({a:''},'a'); proxy= new MyProxy(prim); proxy.get(); 

El resultado es ese console.log (Label2); nos dará un objeto Proxy, después de lo cual Proxy funcionará tanto en el objetivo como en el accesorio (ver Etiqueta1); Pero el código parece funcionar. De qué bañarse.

El método comienza a comunicarse con el objeto (esto) a través de Proxy. Esto es conveniente y lógico cuando escribimos reflexión (reflexión de las propiedades del objeto y cambios en el comportamiento sin cambiar el objeto). Pero si no lo necesitamos y necesitamos el método para trabajar específicamente con el objeto de destino, ¿qué debemos hacer? ¿Por qué ralentizamos el código?

Además, si introducimos más lógica, por ejemplo, filtros de propiedad, etc., el código puede doblarse accidentalmente. Y al escribir código reactivo, hay un "vuelco". (Por ejemplo, al solicitar un método y su posterior ejecución, el método solicita propiedades a través de servidores proxy para los que ya se han publicado eventos). Es decir, los eventos comienzan a dispararse donde no es necesario y no se esperaban.

Como arreglar


Como se entiende, esto ya se anula para el método antes de llamar a Handler.get en Proxy. Solo necesita redefinirlo nuevamente de la siguiente manera:

 let answer=target[prop]; if(typeof target[prop] ==='function'){ answer=target[prop].bind(target); } 

Obtenemos el siguiente código:

 class MyProxy{ constructor(target){ return new Proxy(target,this); } get(target,prop){ //     valueOf.       get let answer=target[prop]; if(typeof target[prop] ==='function'){ answer=target[prop].bind(target); } return answer; } } class PrimitiveType { constructor(target,prop) { this.target=target; this.prop=prop; } get(){ console.log(this); return this.target[this.prop]; } } prim=new PrimitiveType({a:''},'a'); proxy= new MyProxy(prim); proxy.get(); 

Finalmente, como un bono.


Creando una cadena de reactividad / reflexión. Cada objeto anidado será un proxy:

 class MyProxy{ constructor(target){ return new Proxy(target,this); } get(target,prop){ let answer; let tp=target[prop];//    target - Proxy  target[prop] -getter if(typeof tp==='object' && tp!==null){ answer =new MyProxy(tp); } else if(typeof tp ==='function'){ //   .       answer=tp.bind(target); } else { answer=tp; } return answer; } } class PrimitiveType { constructor(target,prop) { this.target=target; this.prop=prop; } valueOf(){ console.log(this); return this.target[this.prop]; } } prim=new PrimitiveType({a:''},'a'); qwer={q:prim}; proxy= new MyProxy(qwer); proxy.q 

Gracias por su atencion!

Source: https://habr.com/ru/post/454292/


All Articles