⬆️ ⬇️

Js. Proxy Reef you need to know about

This article will be interesting to those who use Proxy, for reactivity or reflection.

The behavior of the JS methods is well known to us if we simply use them within the object.

If a method is passed through a property to another object, then it works with the this, which is defined within another object.



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


This must be clearly understood when using a 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(); 


The result will be that console.log (Label2); will give us a Proxy object, after which the Proxy will work on both the target and prop (see Label1); but the code seems to work. What to bathe.



The method begins to communicate with the object (this) through a proxy This is convenient and natural when we write reflection (reflection of the properties of the object and changes in behavior without changing the object). But if we don’t need it and we need the method to work specifically with the target object, what should we do? Why do we need to slow down the code?

')

Moreover, if we introduce more logic, for example, property filters, etc., the code may accidentally be bent. And when writing a reactive code, it goes off scale. (For example, when requesting a method and then executing it, the method requests properties via a proxy for which events are already hung). Ie events start to work where it is not necessary and they were not expected.



How to fix



As understood, this has already been redefined for the method before calling Handler.get in Proxy. You just have to redefine it again as follows:



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


We will get this code:



 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(); 


Finally as a bonus.



Creating a chain of reactivity / reflection. Each attached object will be a 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 


Thanks for attention!

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



All Articles