【问题标题】:Is it possible to override the "call" function?是否可以覆盖“呼叫”功能?
【发布时间】:2011-09-07 06:51:48
【问题描述】:

是否可以在通用级别上覆盖“调用”函数,以便每次在应用程序中的任何位置调用方法时,都会发生一些事情。

我尝试覆盖 Object.call,但尽管我设法做到了,但它并没有改变我的应用程序的工作方式。

顺便说一句,即使它有效,我应该每次都显式调用“foo.call(this,args)”,还是正常的函数调用也可以“foo(args)”?

【问题讨论】:

  • 你在想Function.call吗? Object.prototype上没有方法call
  • 也许你可以解释你真正想要完成的事情。我认为您无法在 javascript 级别拦截每个 javascript 函数调用。你可能需要访问 JS 引擎中的一些钩子才能做到这一点。

标签: javascript


【解决方案1】:

听起来你想在这里做一些面向方面的编程......

JavaScript 作为一种 ECMAScript 方言,确实具有 可调用对象 的概念。每个可调用对象都有一个名为[[Call]]内部属性。该属性在 ECMA-262 规范第 5 版的第 8.6.2 节表 9 中进行了描述。它说:

执行与对象关联的代码。通过函数调用表达式调用。 SpecOp 的参数是一个 this 对象和一个包含传递给函数调用表达式的参数的列表。实现此内部方法的对象是可调用的。只有作为宿主对象的可调用对象才能返回引用值。

但需要注意的是 [[Call]] 是一个内部属性,规范中说:

内部属性没有名称,不能通过 ECMAScript 语言运算符直接访问。内部属性的存在纯粹是为了规范目的。

所以你不能在你自己的 JavaScript 代码中挂钩这个机制。

现在两个方法在Function.prototypeapplycall 中定义。确实,如果您更改Function.prototype.call 的定义,那么如果您创建自己的函数f,那么f.call 确实(除非在f 的原型或f 本身中被覆盖)执行该代码。如您所料,这不会通过直接调用f 自动发生。您必须显式调用call 方法。

话虽如此,最好不要在内置对象的原型中使用预定义的标准方法。库和应用程序中的许多现有代码都依赖于Function.prototype.call。不要惹它。当然,您可以通过多种方式实现一种 AOP 行为。一种是向Function.prototype 添加其他方法,但也不要这样做。另一种是使用 before 和 after 钩子编写自己的调用方法:

function call(theThis, before, main, after, beforeArgs, mainArgs, afterArgs) {
    before.apply(theThis, beforeArgs);
    main.apply(theThis, mainArgs);
    after.apply(theThis. afterArgs);
}

【讨论】:

  • 我总是缓存原始调用函数的副本并在最后调用它
【解决方案2】:

换句话说,您想拦截您的应用程序完成的任何函数调用?没有办法做到这一点,至少在某些通用层面上没有。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 2012-03-11
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 2020-04-18
    • 2014-12-08
    相关资源
    最近更新 更多