2016-04-02 3 views
18

Я хотел бы проверить, является ли объект JavaScript Proxy. Нетривиальный подходКак проверить, является ли объект прокси?

if (obj instanceof Proxy) ... 

здесь не работает, и не проходя по цепочке прототипов для Proxy.prototype, так как все необходимые операции эффективны при поддержке основной целью.

Можно ли проверить, является ли произвольный объект прокси-сервером?

+0

Может быть прокси прокси? Я имею в виду прокси-функцию Proxy перед любым скриптом, связанным с прокси-сервером. – user943702

+0

Не самая ли цель прокси, которую вы не можете отличить от «нормального» объекта? Почему вы хотите проверить это? – Bergi

+1

@ Bergi хорошо, конечно, это не _main_ цель прокси. В остальном я немного удивлен, что вы не можете найти вариант использования этого теста. –

ответ

8

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

невозможно определить, является ли объект прокси или нет (прозрачный виртуализация).

+9

Я бы не связал статью, которая начинается с примечания «* это сообщение в блоге устарело *» :-) Однако, http://exploringjs.com/es6/ch_proxies.html утверждает, что точно такое же – Bergi

+0

@ Комментарий Берги должен быть принятым ответом – BrassApparatus

+1

@BrassApparatus Фактически, оказывается, что и его комментарий, и мой ответ неверны, как подробно [здесь] (http://exploringjs.com/es6/ch_proxies.html#_pitfall-not -all-объекты-может-быть обернуты-прозрачно-на-прокси). –

0

Существует два способа проксирования объекта. Один из них - new Proxy, другой - Proxy.revocable. Мы можем следить за ними, чтобы прокси-объект записывался в секретный список. Затем мы определяем, что объект является прокси-объектом, проверяя, существует ли в секретном списке.

Чтобы воспользоваться функциями шпиона, мы можем написать обертку или использовать встроенный прокси. Последнее означает, что использование прокси-сервера для прокси new Proxy, а также Proxy.recovable, вот fiddle для демонстрации идеи.

Чтобы служить как nodejs-v5.8.0 Proxy, мы можем применить ту же самую идею, используя Proxy.createFunction проксировать Proxy.create и Proxy.createFunction.

+0

Этот подход не будет работать для прокси-серверов, созданных в других сферах (например, iframes или модулей 'vm' узла), потому что вы не можете отслеживать глобальные переменные (например,« Прокси ») в других сферах. – LJHarb

9

В моем текущем проекте мне также нужно было определить, было ли что-то уже прокси, главным образом потому, что я не хотел запускать прокси-сервер на прокси-сервере. Для этого я просто добавил добытчик к моему обработчику, который будет возвращать истину, если запрашиваемые переменной был «__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; 
 
}

не может быть лучшим решением, но я думаю, что это элегантное решение, которое также не появляется при сериализации.

+0

Спасибо! Я занимаюсь каким-то глубоким прокси-сервером, и я тоже попадал в эту проблему. –

+1

Отлично, я использую этот подход, но с небольшим завихрением: const IS_PROXY = Символ («is-proxy»); ... если (! Obj [IS_PROXY]) –

1

Кажется, нет никакого стандартного способа, но для Firefox привилегированного кода, который вы можете использовать

Components.utils.isProxy(object); 

Например:

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

Лучший метод, который я нашел создает слабый набор прокси-объекты. Вы можете сделать это рекурсивно, когда будете строить и проверять свои прокси-объекты.

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

Или

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 
Смежные вопросы