2011-09-07 97 views
8

是否有可能重写通用级别的“调用”函数,以便每次在应用程序中的任何位置调用方法时,都会发生一些情况。是否可以重写“调用”函数?

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

顺便说一句,即使它工作,我应该每次显式调用“foo.call(this,args)”,或者普通函数调用也可以工作“foo(args)”?

+0

您是否想过'Function.call'?在Object.prototype上没有方法调用。 –

+0

也许你可以解释你真正想要完成的事情。我不认为你可以拦截JavaScript级别的每个JavaScript函数调用。你可能必须有权访问JS引擎中的一些钩子才能做到这一点。 – jfriend00

回答

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); 
} 
+0

我总是缓存原始调用函数的副本,并在最后调用它 – user802232

0

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

相关问题