Javascript 如何获取代理';代理对象的处理程序?

Javascript 如何获取代理';代理对象的处理程序?,javascript,ecmascript-6,es6-proxy,Javascript,Ecmascript 6,Es6 Proxy,例如,如果我有这个处理程序/代理(来自) 是否有可能以某种方式探测代理,p,使我能够获取处理程序对象 大致如下: p.__handler__ // returns handler object -> Object {get: handler.get(), set: handler.set(), ...} p.__handler__.get // returns get prop/fn of handler -> function(target, name){ ...} 显然,

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

是否有可能以某种方式探测代理,
p
,使我能够获取
处理程序
对象

大致如下:

p.__handler__   // returns handler object -> Object {get: handler.get(), set: handler.set(), ...}
p.__handler__.get  // returns get prop/fn of handler -> function(target, name){ ...}
显然,在处理程序中设置的各种陷阱对于代理仍然是“已知”的,但是是否有一种明确的方法从代理本身返回它们/处理程序?如果是,怎么做?


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

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]]
}
将“特殊”自描述符属性添加到getOwnPropertyDescriptor

const目标={
//Fns。。
//道具。。。
};
常量处理程序={
getOwnPropertyDescriptor(目标,道具){
如果(prop==“[[handler]]”){
返回{可配置:true,可枚举:true,值:this};
}
返回未定义;
},
建议1:‘abcd’
};
const proxy=新代理(目标,处理程序);
log(Object.getOwnPropertyDescriptor(代理,[[handler]]]).value.prop1)
如果您想在已经有了代理之后动态更改处理程序/陷阱,我认为这非常有用

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

let newProxyWithDifferentGet = new Proxy(originalProxy, {
  get: (target, key){ ... }
}
如果要访问原始代理的目标:

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

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

如果您不是该代理的作者,那么用户是否可以使用该原始目标是由编写该原始代理的人决定的。如果您不同意该作者关于其封装的观点,这是一个社会问题,而不是一个技术问题,并且这不是ES6代理特有的问题。如果您正在使用开源代码,请向上游发送一份PR,解释您认为用户应该可以使用原始目标的原因,或者只需将他们的代码与您的更改结合使用,并将他们的更新合并到原始回购中即可

你得客气地问。如果代理确实定义了
\uuuuu处理程序\uuuu
属性,它将响应您的请求。代理的关键是不允许用户这样检查它,他们应该像对待任何其他对象一样对待它。如果您是代理的创建者,那么保留对
处理程序
@Bergi的引用就相当简单了,我觉得奇怪的是,“代理点”将由标准以这种方式强制执行。我认为理想情况下,代理的创建者有责任将代理声明为公共/公开或私有,即使95%的“正确”答案是消费者不能检查/扩充它。是的,确切地说,代理创建者可以公开处理程序-只要做
新代理({uuuuu handler\uuuuuuuu:handler},handler)
,如果需要的话。默认情况下它不会公开,因为95%的情况下它是不需要的。@Bergi,啊,我现在明白你的意思了。从你最初的评论来看,这对我来说并不明显。请考虑增加/扩展你的想法作为答案。我认为你所说的/暗示的关于故意隐藏代理的内容是有见地的,而你的解决方案使之成为可能是非常相关的,可能也非常适用于任何想知道这一点的人。那么CHrome呢?
let openedProxy = new Proxy(Object.assign(target, {
  _originalHandler: handler,
  _originalTarget: target
}), handler)