JS. Proxy. Armadilha para conhecer

Este artigo será de interesse para aqueles que usam o Proxy para reatividade ou reflexão.
O comportamento dos métodos JS é bem conhecido para nós se simplesmente os usarmos em um objeto.
Se um método é passado através de uma propriedade para outro objeto, ele trabalha com isso, definido na estrutura de outro objeto.

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

Isso deve ser claramente entendido ao usar o 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(); 

O resultado é esse console.log (Label2); nos fornecerá um objeto Proxy, após o qual o Proxy funcionará tanto no destino quanto no suporte (consulte Label1); mas o código parece funcionar. O que tomar banho.

O método começa a se comunicar com o objeto (this) através do Proxy. Isso é conveniente e lógico quando escrevemos reflexão (reflexão das propriedades do objeto e alterações no comportamento sem alterar o objeto). Mas se não precisamos dele e precisamos do método para trabalhar especificamente com o objeto de destino, o que devemos fazer? Por que desaceleramos o código?

Além disso, se introduzirmos mais lógica, por exemplo, filtros de propriedade etc., o código poderá acidentalmente dobrar. E ao escrever código reativo, há um "rollover". (Por exemplo, ao solicitar um método e sua execução subsequente, o método solicita propriedades por meio de proxies para os quais os eventos já foram publicados). Ou seja, os eventos começam a disparar onde não é necessário e eles não eram esperados.

Como consertar


Como entendido, isso já foi substituído pelo método antes de chamar Handler.get no Proxy. Você só precisa redefinir novamente da seguinte maneira:

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

Nós obtemos o seguinte 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 um bônus.


Criando uma cadeia de reatividade / reflexão. Cada objeto aninhado será um 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 

Obrigado pela atenção!

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


All Articles