Javascript 如何测试对象是否为代理?

Javascript 如何测试对象是否为代理?,javascript,ecmascript-6,proxy-classes,Javascript,Ecmascript 6,Proxy Classes,我想测试一个JavaScript对象是否是一个。琐碎的方法 if (obj instanceof Proxy) ... 在这里不起作用,遍历Proxy.prototype的原型链也不起作用,因为所有相关操作都由底层目标有效支持 是否可以测试任意对象是否为代理?来自: 无法确定对象是否为代理(透明虚拟化) 发件人: 无法确定对象是否为代理(透明虚拟化) 代理对象有两种方法。一个是新代理,另一个是代理。可撤销。我们可以监视它们,以便将代理对象记录到一个秘密列表中。然后,我们通过检查 它存在于秘密列

我想测试一个JavaScript对象是否是一个。琐碎的方法

if (obj instanceof Proxy) ...
在这里不起作用,遍历
Proxy.prototype
的原型链也不起作用,因为所有相关操作都由底层目标有效支持

是否可以测试任意对象是否为代理?

来自:

无法确定对象是否为代理(透明虚拟化)

发件人:

无法确定对象是否为代理(透明虚拟化)


代理对象有两种方法。一个是
新代理
,另一个是
代理。可撤销
。我们可以监视它们,以便将代理对象记录到一个秘密列表中。然后,我们通过检查 它存在于秘密列表中

为了监视函数,我们可以编写包装器或使用内置代理。后者意味着使用Proxy来代理
新的Proxy
以及
Proxy.recovable
,下面是一个示例


为了服务于类似的nodejs-v5.8.0代理,我们可以使用
Proxy.createFunction
将相同的思想应用于代理
Proxy.create
Proxy.createFunction
代理对象有两种方法。一个是
新代理
,另一个是
代理。可撤销
。我们可以监视它们,以便将代理对象记录到一个秘密列表中。然后,我们通过检查 它存在于秘密列表中

为了监视函数,我们可以编写包装器或使用内置代理。后者意味着使用Proxy来代理
新的Proxy
以及
Proxy.recovable
,下面是一个示例


为了服务于类似的nodejs-v5.8.0代理,我们可以使用
Proxy.createFunction
将相同的思想应用于代理
Proxy.create
Proxy.createFunction

在我当前的项目中,我还需要一种方法来定义某个东西是否已经是代理,主要是因为我不想在代理上启动代理。为此,我只向我的处理程序添加了一个getter,如果请求的变量是“\uuuproxy”,则返回true:

功能_观察(obj){
如果(对象_uuisproxy==未定义){
var ret=新代理(obj | |{}{
设置:(目标、键、值)=>{
///根据变化采取行动
返回true;
},
get:(目标,关键点)=>{
如果(键!==“\uu isProxy”){
返回目标[键];
}
返回true;
}
});
返回ret;
}
返回obj;

}
在我当前的项目中,我还需要一种方法来定义某个东西是否已经是代理,主要是因为我不想在代理上启动代理。为此,我只向我的处理程序添加了一个getter,如果请求的变量是“\uuuproxy”,则返回true:

功能_观察(obj){
如果(对象_uuisproxy==未定义){
var ret=新代理(obj | |{}{
设置:(目标、键、值)=>{
///根据变化采取行动
返回true;
},
get:(目标,关键点)=>{
如果(键!==“\uu isProxy”){
返回目标[键];
}
返回true;
}
});
返回ret;
}
返回obj;

}
似乎没有标准方法,但对于Firefox特权代码,您可以使用

Components.utils.isProxy(object);
例如:

Components.utils.isProxy([]); // false
Components.utils.isProxy(new Proxy([], {})); // true
const target = {};
const proxy = new Proxy(target, {});
util.types.isProxy(target);  // Returns false
util.types.isProxy(proxy);  // Returns true

似乎没有标准的方法,但对于Firefox特权代码,您可以使用

Components.utils.isProxy(object);
例如:

Components.utils.isProxy([]); // false
Components.utils.isProxy(new Proxy([], {})); // true
const target = {};
const proxy = new Proxy(target, {});
util.types.isProxy(target);  // Returns false
util.types.isProxy(proxy);  // Returns true

我发现最好的方法是创建一组弱代理对象。在构建和检查代理对象时,可以递归地执行此操作

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

    if(myProxySet.has(myObj)) {
        // Working with a proxy object.
    }

我发现最好的方法是创建一组弱代理对象。在构建和检查代理对象时,可以递归地执行此操作

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

    if(myProxySet.has(myObj)) {
        // Working with a proxy object.
    }

事实上,确定对象是否为代理存在一种变通方法,它基于几个假设。首先,通过C++扩展或浏览器中的特权网页,当页面可以启动不安全的扩展时,可以方便地解决代理代码确定问题。其次,代理是相对较新的功能,所以它不存在于旧的浏览器中-所以解决方案只适用于现代浏览器

JS引擎无法克隆函数(因为它们绑定到激活上下文和其他一些原因),但根据定义,代理对象由包装处理程序组成。所以,要确定对象是否是代理,启动强制对象克隆就足够了。可以通过函数来完成


若对象是代理,即使它不包含任何函数,也将无法复制。例如,Edge和Chrome在尝试发布代理对象时产生以下错误:
[object DomeException]:{code:25,消息:“DataCloneError”,名称:“DataCloneError”}
未能在“窗口”上执行“postMessage”:[object object object]无法克隆。
事实上,确定对象是否为代理存在一种变通方法,它基于几个假设。首先,通过C++扩展或浏览器中的特权网页,当页面可以启动不安全的扩展时,可以方便地解决代理代码确定问题。其次,代理是相对较新的功能,所以它不存在于旧的浏览器中-所以解决方案只适用于现代浏览器

JS引擎无法克隆函数(因为它们绑定到激活上下文和其他一些原因),但根据定义,代理对象由包装处理程序组成。所以,要确定对象是否是代理,启动强制对象克隆就足够了。可以通过函数来完成

若对象是代理,即使它不包含任何函数,也将无法复制。例如,Edge和Chrome在尝试发布代理对象时产生以下错误:
[object DomeException]:{code:25,消息:“DataCloneError”,名称:“DataCloneError”}
未能在“窗口”上执行“postMessage”:[object object object]无法克隆。
在Node.js 10中,您可以
const proxy_set = new WeakSet()
window.Proxy = new Proxy(Proxy,{
      construct(target, args) {
        const proxy = new target(...args)
        proxy_set.add(proxy)
        return proxy
      }
})
const a = external_script()
console.log(proxy_set.has(a)) //true
  const is_proxy = Symbol('is_proxy')
  const old_Proxy = Proxy
  const handler = {
    has (target, key) {
      return (is_proxy === key) || (key in target)
    }
  }
  window.Proxy = new Proxy(Proxy,{
      construct(target, args) {
          return new old_Proxy(new target(...args), handler)
      }
  })
  const a = external_script()
  console.log(is_proxy in a) //true
function getProxy(target, property) {
    if (property === Symbol.for("__isProxy")) return true;
    if (property === Symbol.for("__target")) return target;
    return target[property];
}

function setProxy(target, property, value) {
    if (property === Symbol.for("__isProxy")) throw new Error("You cannot set the value of '__isProxy'");
    if (property === Symbol.for("__target")) throw new Error("You cannot set the value of '__target'");
    if (target[property !== value]) target[property] = value;
    return true;
}

function isProxy(proxy) {
    return proxy == null ? false : !!proxy[Symbol.for("__isProxy")];
}

function getTarget(proxy) {
    return isProxy(proxy) ? proxy[Symbol.for("__target")] : proxy;
}

function updateProxy(values, property) {
    values[property] = new Proxy(getTarget(values[property]), {
        set: setProxy,
        get: getProxy
    });
}
function shouldBeCloneable(o) {
    const type = typeof o;
    return (
        type === "undefined" ||
        o === null ||
        type === "boolean" ||
        type === "number" ||
        type === "string" ||
        o instanceof Date ||
        o instanceof RegExp ||
        o instanceof Blob ||
        o instanceof File ||
        o instanceof FileList ||
        o instanceof ArrayBuffer ||
        o instanceof ImageData ||
        o instanceof ImageBitmap ||
        o instanceof Array ||
        o instanceof Map ||
        o instanceof Set
    );
}

function isCloneable(obj) {
    try {
        postMessage(obj, "*");
    } catch (error) {
        if (error?.code === 25) return false; // DATA_CLONE_ERR
    }

    return true;
}

function isProxy(obj){
    const _shouldBeCloneable = shouldBeCloneable(obj);
    const _isCloneable = isCloneable(obj);

    if(_isCloneable) return false;
    if(!_shouldBeCloneable) return "maybe";
    
    return _shouldBeCloneable && !_isCloneable;
}

console.log("proxied {}", isProxy(new Proxy({},{})));
console.log("{}", isProxy({}));

console.log("proxied []", isProxy(new Proxy([],{})));
console.log("[]", isProxy([]));

console.log("proxied function", isProxy(new Proxy(()=>{},{})));
console.log("function", isProxy(()=>{}));

console.log("proxied Map", isProxy(new Proxy(new Map(),{})));
console.log("new Map()", isProxy(new Map()));

class A{};
console.log("proxied class", isProxy(new Proxy(A,{})));
console.log("class", isProxy(A));

console.log("proxied class instance", isProxy(new Proxy(new A(),{})));
console.log("class instance", isProxy(new A()));