如何在javascript中将代理对象作为上下文传递给闭包

如何在javascript中将代理对象作为上下文传递给闭包,javascript,scope,closures,bind,anonymous-function,Javascript,Scope,Closures,Bind,Anonymous Function,注意:我现在相信这个问题是基于对javascript规范的假设,而javascript规范实际上是特定于实现的。 我正在尝试为一个复杂的动态javascript应用程序构建一个运行时调试钩子系统。通过一系列选择,我可以选择使用javascript代理和反射元编程结构在我正在调试的应用程序中插入函数调用,将所有传入函数参数包装在代理/反射结构中 该方法涉及用代理替换高级应用程序函数,并使用陷阱和处理程序提供调试功能,最终以透明的方式将参数传递给应用程序。所有属性get/set和函数的执行都正常。但

注意:我现在相信这个问题是基于对javascript规范的假设,而javascript规范实际上是特定于实现的。

我正在尝试为一个复杂的动态javascript应用程序构建一个运行时调试钩子系统。通过一系列选择,我可以选择使用javascript代理和反射元编程结构在我正在调试的应用程序中插入函数调用,将所有传入函数参数包装在代理/反射结构中

该方法涉及用代理替换高级应用程序函数,并使用陷阱和处理程序提供调试功能,最终以透明的方式将参数传递给应用程序。所有属性get/set和函数的执行都正常。但是,通过将所有对象和函数包装在代理中,可以跟踪运行时

我正在将这个挂钩系统安装到Chrome中

(注意:请不要提供建议调试挂钩的不同方法的答案-选项已经过广泛评估。)

问题是应用程序中的一些javascript方法调用闭包并传递“this”参数。当“this”参数包装在代理中时,运行时无法执行闭包,而是引发“非法调用”异常

typeof this === 'object'
true
我已经尝试重新设计调试钩子系统,使其不包装某些方法的参数,或者有选择地包装参数。我一直无法找到一种方法来判断一个参数是否打算用作上下文,使尝试这种方法的代码硬编码到许多可能的方法并调用约定。最终,这对于调用约定边缘案例来说太脆弱,需要太多的案例语句

我还删除了在传递参数之前包装参数的逻辑。这消除了调试挂接系统的优点,因此我总是还原逻辑来包装所有传入参数

alert.apply(this, [1]);

p = new Proxy(this, {});

try {
    alert.apply(p, [1]);
} catch (e) {
    console.log(e);
}
这会引发“非法调用”异常

typeof this === 'object'
true
但似乎上下文和其他事物一样都是对象

我希望通过将Proxy()传递给上下文在调用中应该会成功。除此之外,我希望上下文的类型足够具体,以确定它是否应该包装在Proxy()中

我有两个问题

(1) javascript中上下文绑定闭包的语义是什么,它会导致到代理(上下文)的绑定因非法调用而失败

(2) 上下文是什么类型的对象,javascript方法如何通过在运行时检查其属性来区分上下文和其他javascript对象

上下文是什么类型的对象,javascript方法如何通过在运行时检查其属性来区分上下文和其他javascript对象

没有特殊类型。每个对象都可以通过对其调用方法而成为上下文。大多数将成为方法调用上下文的对象都将该方法作为(继承的)属性,但不能保证

你不能把他们分开

javascript中上下文绑定的语义是什么,它会导致到代理(上下文)的绑定因非法调用而失败

当方法是本机方法时。在用户代码函数中,
this
上下文作为代理没有任何区别,当您访问它时,它将只是作为代理

问题是本机方法期望它们的
参数是相应类型的本机对象。当然,这些对象仍然是javascript对象,但它们也可能包含内部属性的私有数据。代理的目标和处理程序引用也通过此类内部属性实现,例如,您有时可以在调试器中检查它们。本机方法不知道如何展开代理并使用其目标,它们只是查看对象,并注意到它没有方法执行其工作所需的内部属性。您也可以传递一个普通的
{}

这些方法的示例可以在ECMAScript运行时的内置程序中找到:

而且(甚至更多)作为环境提供的宿主对象:

  • 窗口。警报
    /
    提示
  • EventTarget.prototype.addEventListener
    /
    removeEventListener
  • document.createElement
  • Element.prototype.appendChild
    /
    删除
    /
    ..
  • 真的只是特定于浏览器的任何东西
  • 但也适用于其他环境,如
我尝试过在正确的位置通过边缘编码和一揽子/启发式策略来展开代理

我认为唯一合理的方法是为它们打开所有的参数(包括
这个
参数)

只有少数本机函数可以被列入白名单,例如
Array.prototype
上的大多数函数,它们在语言标准中明确指定用于处理任意对象

上下文是什么类型的对象,javascript方法如何通过在运行时检查其属性来区分上下文和其他javascript对象

没有特殊类型。每个对象都可以通过对其调用方法而成为上下文。大多数将成为方法调用上下文的对象都将该方法作为(继承的)属性,但不能保证

你不能把他们分开

javascript中上下文绑定的语义是什么,它会导致到代理(上下文)的绑定因非法调用而失败

当方法是本机方法时。在用户代码函数中,
this
上下文作为代理并没有什么区别,当您访问它时,它将只是作为一个专业程序