15

例如,如果我有这个处理程序/代理(来自MDN 示例)......

var handler = {
    get: function(target, name){
        return name in target?
            target[name] :
            37;
    }
};

var p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;

console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37

是否有可能以p某种方式探测代理,让我取回handler对象。

类似于以下内容:

p.__handler__   // returns handler object -> Object {get: handler.get(), set: handler.set(), ...}
p.__handler__.get  // returns get prop/fn of handler -> function(target, name){ ...}

显然,处理程序中设置的各种陷阱对于代理来说仍然是“已知的”,但是有没有一种明确的方法可以从代理本身返回它们/处理程序?如果是这样,怎么做?

目前我没有具体的用例,但是如果您想在已经拥有代理后动态更改处理程序/陷阱,我可以看到这很有用。

4

3 回答 3

10

ECMAScript 无法访问内部 [[ProxyHandler]] 或 [[ProxyTarget]] 插槽。

有些实现可能会提供一些非标准的方式,但不要想当然。

例如,在 Firefox 特权代码上,您可以使用

Components.utils.isProxy(object);

我建议实施类似的方法来公开 [[ProxyHandler]] 和 [[ProxyTarget]]。他们告诉我实施它们Debugger.Object而不是Components.utils.

当补丁落地时,可以使用类似的东西

Components.utils.import('resource://gre/modules/jsdebugger.jsm');
var Cc = Components.classes;

// Add a debugger to a new global
var global = new Components.utils.Sandbox(
  Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal),
  { freshZone: true }
);
addDebuggerToGlobal(global);
var dbg = new global.Debugger().addDebuggee(this);

// Create a debugger object of your object, and run proxy getters
var dbgObj = dbg.makeDebuggeeValue(object);
if(dbgObj.isProxy) { // a boolean
  dbgObj.proxyHandler.unsafeDereference(); // the [[ProxyHandler]]
  dbgObj.proxyTarget.unsafeDereference(); // the [[ProxyTarget]]
}
于 2016-07-14T23:20:40.430 回答
6

向 getOwnPropertyDescriptor 添加“特殊”自描述符属性

const target = {
  //Fns ..
  //Props ...
};

const handler = {
  getOwnPropertyDescriptor(target, prop) {
    if(prop == "[[handler]]"){
        return { configurable: true, enumerable: true, value: this };
    }
    return undefined;
  },
  prop1: 'abcd'
  
};

const proxy = new Proxy(target, handler);

console.log(Object.getOwnPropertyDescriptor(proxy, '[[handler]]').value.prop1);

于 2018-06-19T02:32:27.250 回答
0

如果您想在已经拥有代理后动态更改处理程序/陷阱,我可以看到这很有用

如果您只想在您已经有权访问的(代理)对象上添加处理程序:您可以通过创建一个处理您要更改的特定陷阱的新代理来实现这一点,例如:

let newProxyWithDifferentGet = new Proxy(originalProxy, {
  get: (target, key){ ... }
}

如果您想访问原始代理的目标:

如果您是原始 Proxy 的作者,您可以在构建它时执行以下操作:

let openedProxy = new Proxy(Object.assign(target, {
  _originalHandler: handler,
  _originalTarget: target
}), handler)

如果您不是作者,那么该原始目标是否对用户可用是由编写该原始代理的人决定的。如果您不同意该作者的封装,那是一个社会问题,而不是技术问题,而且这不是 ES6 代理所特有或独有的。如果您正在使用开源代码,请向上游发送 PR,解释为什么您认为原始目标应该对用户可用,或者只是用您的更改分叉他们的代码并使用它,然后将他们的更新合并到原始存储库。

于 2018-11-02T06:32:15.327 回答