简体   繁体   English

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

[英]Can Function.prototype.call be overloaded to log all function calls?

I've try to change Function.prototype.call to console.log all functions calls (for debugging), but my browser crashed, is it possible? 我试图将Function.prototype.call更改为console.log所有函数调用(用于调试),但我的浏览器崩溃了,是否可能? If yes how the code should look like? 如果是,代码应该如何?

I've try to do something like this: 我试着这样做:

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

but got lots of toString() { [Native code] } when I move the mouse over the page, and I needed to kill that tab were I call that code. 但是当我将鼠标移到页面上时,得到了很多toString() { [Native code] } ,我需要杀掉那个标签,我称之为代码。

tldr; tldr; No, it's not possible to intercept every function call by some sort of universal getter. 不,通过某种通用的getter拦截每个函数调用是不可能的。

Function.prototype.call is not called each time you call a function, but is used to pass another thisArg when calling a function, meaning it's not implicitly called when invoking a function. 每次调用函数时都不调用Function.prototype.call ,但在调用函数时用于传递另一个thisArg ,这意味着在调用函数时不会隐式调用它。


The nearest you could get would be iterating over all globally accessible functions or an array of references to functions you're interested in, and patching each and every one. 你可以得到的最接近的是迭代所有全局可访问的函数或对你感兴趣的函数的引用数组,并修补每一个函数。

However, this also implies that you can only intercept those functions, you already know about. 但是,这也意味着你只能拦截那些你已经知道的功能。 If a function is not globally accessible, eg contained in a Lexical Environment, hidden from your code, or was declared after your function ran, you won't catch it. 如果函数不是全局可访问的,例如包含在词法环境中,隐藏在代码中,或者在函数运行后声明,则不会捕获它。

So while you can override a single function, or define a getter for it, it's unfortunately not possible to generally intercept every function call. 因此,虽然您可以覆盖单个函数,或者为它定义一个getter,但遗憾的是,通常无法拦截每个函数调用。

If you, however want to catch all functions called via Function.prototype.call you can indeed override it. 但是,如果您希望捕获通过Function.prototype.call调用的所有函数,则可以覆盖它。

There are 2 things you would need to change, in order for this to work. 为了实现这一点,您需要更改两件事。

  1. Since you pass an object ( this ) to console.log, Object.prototype.toString gets call ed with that object as thisArg . 由于您将对象( this )传递给console.log,因此Object.prototype.toString将使用该对象作为thisArg call ed。 And you end up in an infinite loop. 而你最终陷入了无限循环。
  2. You don't return the result of the call to the original Function.prototype.call call. 您不会将调用的结果返回到原始的Function.prototype.call调用。 Which breaks code that relies on this return value. 这会破坏依赖此返回值的代码。

Given this, a slightly modified version should log the names of the functions, call is being invoked on. 鉴于此,稍微修改的版本应记录函数的名称,调用正在调用。

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

However. 然而。 It seems you want to catch any function, called. 看来你想要捕捉任何被称为的功能。 This won't be possible this way, only functions, invoked using Function.prototype.call can be intercepted. 这种方式不可能,只能拦截使用Function.prototype.call调用的Function.prototype.call

I have found that I've crashed more than one browser with excessive logging... that sounds like a recipe for disaster. 我发现我已经崩溃了不止一个浏览器过多的日志...这听起来像是灾难的秘诀。

In addition, most (all?) modern browsers make that property read-only to keep a 3rd party script from spying on what is happening on the system. 此外,大多数(所有?)现代浏览器将该属性设置为只读,以防止第三方脚本监视系统上发生的事情。

Your best bet is to use the profiling tools in FireFox or Chrome to track what is happening. 最好的办法是使用FireFox或Chrome中的分析工具来跟踪发生的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM