可以重载Function.prototype.call来记录所有函数调用吗?

时间:2014-05-05 12:41:14

标签: javascript debugging prototype

我尝试将Function.prototype.call更改为console.log所有函数调用(用于调试),但是我的浏览器崩溃了,是否可能?如果是,代码应该如何?

我尝试做这样的事情:

(function(call) {
  Function.prototype.call = function() {
    console.log(this);
    call.apply(this, arguments);
  };
})(Function.prototype.call);

但是当我将鼠标移到页面上时会得到很多toString() { [Native code] },如果我调用该代码,我需要杀死该标签。

2 个答案:

答案 0 :(得分:2)

<强> tldr; 不,通过某种通用的getter拦截每个函数调用是不可能的。

每次调用函数时都不调用

Function.prototype.call,但在调用函数时用于传递另一个thisArg,这意味着在调用函数时不会隐式调用它。


你可以得到的最接近的是迭代所有全局可访问的函数或对你感兴趣的函数的引用数组,并修补每一个函数。

但是,这也意味着你只能截获那些你已经知道的功能。 如果功能不可全局访问,例如包含在词法环境中,隐藏在您的代码之外,或者在您的函数运行后声明,您将无法捕获它。

因此,虽然您可以覆盖单个函数,或者为它定义一个getter,但遗憾的是,通常无法拦截每个函数调用。

但是,如果您希望捕获通过Function.prototype.call调用的所有函数,则可以覆盖它。

为了实现这一点,您需要更改两件事。

  1. 由于您将对象(this)传递给console.log,Object.prototype.toStringcall作为thisArg获取该对象。而你最终会陷入无限循环。
  2. 您不会将通话结果返回原始Function.prototype.call来电。这会破坏依赖此返回值的代码。
  3. 鉴于此,略微修改的版本应该记录函数的名称,调用正在调用。

    (function(call) {
      Function.prototype.call = function() {
        console.log(this.toString ());
        return call.apply(this, arguments);
      };
    })(Function.prototype.call);
    

    然而。您似乎想要捕获任何函数,称为。这种方式是不可能的,只有使用Function.prototype.call调用的函数才能被截获。

答案 1 :(得分:1)

我发现我已经崩溃了多个浏览器过多的日志...这听起来像是灾难的秘诀。

此外,大多数(全部?)现代浏览器将该属性设置为只读,以防止第三方脚本监视系统上发生的事情。

最好的办法是使用FireFox或Chrome中的分析工具来跟踪发生的情况。