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

IT技术 javascript ecmascript-6 proxy-classes
2021-03-19 02:17:39

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

if (obj instanceof Proxy) ...

在这里不起作用,也不能遍历 的原型链Proxy.prototype,因为所有相关操作都得到了底层目标的有效支持。

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

6个回答

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

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;
}

可能不是最好的解决方案,但我认为这是一个优雅的解决方案,在序列化时也不会弹出。

谢谢!我正在做某种深度代理,我也遇到了这个问题。
2021-05-02 02:17:39
太好了,我正在使用这种方法,但有一点小改动: const IS_PROXY = Symbol("is-proxy"); ...如果 (!obj[IS_PROXY])
2021-05-03 02:17:39
@MatthewJoelRodríguezLlanos 只要确保符号存储在某个闭包中,因为Symbol("is-proxy") !== Symbol("is-proxy"),或者您使用的Symbol.for
2021-05-10 02:17:39
这仅适用于您可以控制创建代理陷阱的情况。
2021-05-20 02:17:39

在 Node.js 10 中,您可以使用util.types.isProxy.

例如:

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

创建一个新符号:

let isProxy = Symbol("isProxy")

get您的代理处理程序方法中,您可以检查 是否key是您的符号,然后return true

get(target, key)
{
    if (key === isProxy)
        return true;

    // normal get handler code here
}

然后,您可以使用以下代码检查对象是否是您的代理之一:

if (myObject[isProxy]) ...
@snewcomer 谢谢。没错,我认为这满足了常见的用例。(我个人认为您不应该检查外部对象是否是代理,因为您正在编写特定于实现的代码并首先覆盖代理的整个抽象性质/目的)。
2021-05-16 02:17:39
有趣的!仅供其他人注意,这仅在您控制代理获取陷阱时才有效。否则,如果您不拥有该对象,这将不起作用。
2021-05-17 02:17:39

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

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

我不会链接以注释开头的文章“此博客文章已过时”:-) 但是,explorationjs.com/ es6/ ch_proxies.html声明完全相同
2021-05-01 02:17:39
@BrassApparatus 实际上,事实证明他的评论和我的回答都是错误的,详见此处
2021-05-14 02:17:39

添加“支持” instanceof Proxy

我不推荐它,但是如果您想添加对 的支持instanceof,您可以在实例化任何代理之前执行以下操作:

(() => {
  var proxyInstances = new WeakSet()
  
  // Optionally save the original in global scope:
  originalProxy = Proxy

  Proxy = new Proxy(Proxy, {
    construct(target, args) {
      var newProxy = new originalProxy(...args)
      proxyInstances.add(newProxy)
      return newProxy
    },
    get(obj, prop) {
      if (prop == Symbol.hasInstance) {
        return (instance) => {
          return proxyInstances.has(instance)
        }
      }
      return Reflect.get(...arguments)
    }
  })
})()

// Demo:

var a = new Proxy({}, {})
console.log(a instanceof Proxy) // true
delete a

var a = new originalProxy({}, {})
console.log(a instanceof Proxy) // false
delete a

Yo dawg,我听说你喜欢代理,所以我把代理放在你的代理中,这样你就可以在创建代理后识别代理。
2021-04-23 02:17:39