2016-04-02 20 views
18

Vorrei verificare se un oggetto JavaScript è un Proxy. L'approccio banaleCome verificare se un oggetto è un Proxy?

if (obj instanceof Proxy) ... 

non funziona qui, né che attraversa la catena di prototipi per Proxy.prototype, dal momento che tutte le operazioni rilevanti sono effettivamente sostenuti dal target sottostante.

È possibile verificare se un oggetto arbitrario è un Proxy?

+0

Forse delega Proxy? Intendo proxy la funzione Proxy prima di qualsiasi script che coinvolge Proxy. – user943702

+0

Non è proprio lo scopo dei proxy che non è possibile distinguerli da un oggetto "normale"? Perché vorresti testarlo? – Bergi

+1

@ Bene bene, certamente questo non è lo scopo principale dei proxy. Per il resto, sono un po 'sorpreso che non riesca a capire un caso d'uso per questo test. –

risposta

8

Da http://www.2ality.com/2014/12/es6-proxies.html:

È impossibile determinare se un oggetto è un proxy o meno (virtualizzazione trasparente).

+9

Non vorrei collegare un articolo che inizia con una nota "* questo post del blog è obsoleto *" :-) Tuttavia, http://exploringjs.com/es6/ch_proxies.html afferma esattamente lo stesso – Bergi

+0

@ Il commento di Bergi dovrebbe essere la risposta accettata – BrassApparatus

+1

@BrassApparatus In realtà, risulta che sia il suo commento sia la mia risposta sono sbagliati, come dettagliato [qui] (http://exploringjs.com/es6/ch_proxies.html#_pitfall-non -all-oggetti-possono-essere-avvolte-trasparente-by-proxy). –

0

Esistono due modi per eseguire il proxy di un oggetto. Uno è new Proxy, un altro è Proxy.revocable. Potremmo spiarli in modo che l'oggetto con proxy sia registrato in una lista segreta. Quindi determiniamo che un oggetto è un oggetto con proxy controllando se lo è nell'elenco segreto.

Per le funzioni di spionaggio, possiamo scrivere wrapper o utilizzare il proxy integrato. Quest'ultimo significa che utilizzare Proxy per il proxy new Proxy e Proxy.recovable, qui è un fiddle per dimostrare l'idea.

per servire il come nodejs-v5.8.0 Proxy, si può applicare la stessa idea utilizzando Proxy.createFunction per delega Proxy.create e Proxy.createFunction.

+0

Questo approccio non funzionerà per i proxy creati in altri reami (come iframe o moduli 'vm' del nodo), perché non è possibile spiare i globali (come' Proxy') in altri regni. – LJHarb

9

Nel mio progetto corrente avevo anche bisogno di un modo per definire se qualcosa fosse già un Proxy, principalmente perché non volevo avviare un proxy su un proxy. Per questo ho semplicemente aggiunto un getter al mio gestore, che restituisce true se la variabile richiesta è stata "__Proxy":

function _observe(obj) { 
 
    if (obj.__isProxy === undefined) { 
 
    var ret = new Proxy(obj || {}, { 
 
     set: (target, key, value) => { 
 
     /// act on the change 
 
     return true; 
 
     }, 
 
     get: (target, key) => { 
 
     if (key !== "__isProxy") { 
 
      return target[key]; 
 
     } 
 

 
     return true; 
 
     } 
 
    }); 
 
    return ret; 
 
    } 
 

 
    return obj; 
 
}

potrebbe non essere la soluzione migliore, ma penso che sia un elegante soluzione, che non viene visualizzata durante la serializzazione.

+0

Grazie! Sto facendo una specie di deep proxy, e anch'io ho avuto questo problema. –

+1

Ottimo, sto usando questo approccio ma con una piccola svolta: const IS_PROXY = Symbol ("is-proxy"); ... if (! Obj [IS_PROXY]) –

1

Sembra che ci sia un modo standard, ma per Firefox codice con privilegi è possibile utilizzare

Components.utils.isProxy(object); 

Ad esempio:

Components.utils.isProxy([]); // false 
Components.utils.isProxy(new Proxy([], {})); // true 
1

Il metodo migliore che ho trovato è la creazione di un insieme debole della oggetti proxy. Puoi farlo in modo ricorsivo quando stai costruendo e controllando i tuoi oggetti con proxy.

var myProxySet = new WeakSet(); 
    var myObj = new Proxy({},myValidator); 
    myProxySet.add(myObj); 

    if(myProxySet.has(myObj)) { 
     // Working with a proxy object. 
    } 
0
class MyProxy{ 
    constructor(target,desc,self=this){ 
      var 
      old_get=('get' in desc)?desc.get:function(target,prop){return target[prop];}, 
      old_has=('has' in desc)?desc.has:function(target,prop){ return (prop in target);}; 
     desc.get=function(target,prop){ 


      if(prop=='getOwnPrototypeOf'){ 
       return function() { 
        return Object.getPrototypeOf(self); 
        /* //if "getOwnPrototypeOf" is defined in "target", then do not override it. 
         if('getOwnPrototypeOf' in target){ //if "target" is MyProxy object. 
          return target.getOwnPrototypeOf(); 
         } else{ 
          return Object.getPrototypeOf(self); 
         } 
        */ 
       } 
      } else if(prop=='getOwnProxyObjectOf') { 
       return function(){ 
        return self; 
       } 
      } 
      return old_get(target,prop); 
     } 
     desc.has=function (target,prop){ 
      if(prop=='getOwnPrototypeOf'|| prop=='getOwnProxyObjectOf'){ 
       return true; 
      } 
      return old_has(target,prop); 
     } 
     return new Proxy(target,desc); 
    } 
} 

// Exemple 
class AsdProxy{ 
    constructor(target,desc,self=this){ 
     self=this; 
     return new MyProxy(target,desc,self); 
    } 

} 
class AsdProxy2{ 
    constructor(target,desc,self=this){ 
     return new MyProxy(target,desc,self); 
    } 

} 
class AsdProxy3 { 
    constructor(target,desc,self=this){ 
     return new AsdProxy2(target,desc,self); 
    } 

} 

ss=new MyProxy({},{}); 
console.log('getOwnPrototypeOf' in ss && MyProxy.prototype===ss.getOwnPrototypeOf());//true 
console.log(ss.getOwnProxyObjectOf() instanceof MyProxy); //true 

asd=new AsdProxy({},{}); 
asd2=new AsdProxy2({},{}); 
asd3 = new AsdProxy3({},{}); 
console.log(asd2.getOwnProxyObjectOf() instanceof MyProxy);// false 
console.log(asd2.getOwnProxyObjectOf() instanceof AsdProxy);//false 
console.log(asd2.getOwnProxyObjectOf() instanceof AsdProxy2); //true 
console.log(asd3.getOwnProxyObjectOf() instanceof AsdProxy2);// false 
console.log(asd3.getOwnProxyObjectOf() instanceof AsdProxy3); // true 
-1

O

class MyProxy{ 
    constructor(target,desc,self=this){ 

     var getMyProxyObject=Symbol.for('getMyProxyObject'), old_get=('get' in desc)?desc.get:function(target,prop){return target[prop];} 
     desc.get=function(target,prop){ 
      if(prop===getMyProxyObject){ 
       return self; 
      } 
      return old_get(target,prop); 
     } 
     return new Proxy(target,desc); 
    } 

} 


class NewProxy extends MyProxy { 
    constructor(target,desc){ 
     return super(target,desc); 
    } 
} 
var getMyProxyObject=Symbol.for('getMyProxyObject'), 
    asd=new MyProxy({},{}), 
    bsd=new NewProxy({},{}); 
console.log(asd[getMyProxyObject] instanceof MyProxy); // true 
console.log(bsd[getMyProxyObject] instanceof MyProxy); // true 
console.log(bsd[getMyProxyObject] instanceof NewProxy); // true 
console.log(NewProxy.prototype.isPrototypeOf(bsd[getMyProxyObject])); //true 
console.log(MyProxy.prototype.isPrototypeOf(bsd[getMyProxyObject])); //true 
Problemi correlati