是否可以覆盖“呼叫”功能?

时间:2011-09-07 06:51:49

标签: javascript

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

我尝试重写Object.call,但是虽然我设法做到了,但它并没有改变我的应用程序的工作方式。

顺便说一句,即使它有效,我是否应该每次都明确调用“foo.call(this,args)”,否则正常的函数调用也会起作用“foo(args)”?

2 个答案:

答案 0 :(得分:8)

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

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其他一些方法,但不要这样做。另一种方法是使用钩子之前和之后编写自己的调用方法:

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

答案 1 :(得分:0)

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