自动将console.log添加到每个功能


97

通过在某个地方注册全局钩子(即,无需修改实际函数本身)或通过其他方式,是否有任何方法可以使任何函数输出console.log语句?


一个非常好的问题,我很想知道这是否可行,但是我很确定这不是...也许添加一个功能请求,以便将其添加到您喜欢的浏览器的js引擎中?:-)
Endophage 2011年

完美的问题,我需要类似的东西
mjimcua 2015年

Answers:


62

这是用您选择的功能扩展全局名称空间中所有功能的方法:

function augment(withFn) {
    var name, fn;
    for (name in window) {
        fn = window[name];
        if (typeof fn === 'function') {
            window[name] = (function(name, fn) {
                var args = arguments;
                return function() {
                    withFn.apply(this, args);
                    return fn.apply(this, arguments);

                }
            })(name, fn);
        }
    }
}

augment(function(name, fn) {
    console.log("calling " + name);
});

不利的一面是,调用后创建的任何函数augment都不会具有其他行为。


它是否正确处理了函数的返回值?
SunnyShah 2012年

2
@SunnyShah不,它不是:jsfiddle.net/Shawn/WnJQ5但这确实是:jsfiddle.net/Shawn/WnJQ5/1,尽管我不确定它在所有情况下都可以工作...区别正在fn.apply(this, arguments);变为return fn.apply(this, arguments);
肖恩

2
@Shawn @SunnyShah已修复。只需向return最里面的功能添加一个。
韦恩

工作正常,但我收到此jquery:call错误:if(jQuery.isFunction(lSrc)),它说:TypeError:jQuery.isFunction不是函数
fekiri malek

4
此解决方案不使用jQuery
Wayne

8

对我而言,这似乎是最优雅的解决方案:

(function() {
    var call = Function.prototype.call;
    Function.prototype.call = function() {
        console.log(this, arguments); // Here you can do whatever actions you want
        return call.apply(this, arguments);
    };
}());

7

记录函数调用的代理方法

有一种使用Proxy来在JS中实现此功能的新方法。假设我们想在console.log调用特定类的函数时拥有一个:

class TestClass {
  a() {
    this.aa = 1;
  }
  b() {
    this.bb = 1;
  }
}

const foo = new TestClass()
foo.a() // nothing get logged

我们可以使用覆盖该类每个属性的Proxy替换类实例化。所以:

class TestClass {
  a() {
    this.aa = 1;
  }
  b() {
    this.bb = 1;
  }
}


const logger = className => {
  return new Proxy(new className(), {
    get: function(target, name, receiver) {
      if (!target.hasOwnProperty(name)) {
        if (typeof target[name] === "function") {
          console.log(
            "Calling Method : ",
            name,
            "|| on : ",
            target.constructor.name
          );
        }
        return new Proxy(target[name], this);
      }
      return Reflect.get(target, name, receiver);
    }
  });
};



const instance = logger(TestClass)

instance.a() // output: "Calling Method : a || on : TestClass"

检查这在Codepen中是否确实有效


请记住,使用Proxy不仅可以记录控制台名称,还可以提供更多功能。

该方法也可以在 Node.js中使用


您还可以不使用实例和类来执行此操作吗?具体说来在node.js中?
Revadike

@Revadike,这应该有所帮助:stackoverflow.com/a/28708700/5284370
Soorena,

1

如果您想要更有针对性的日志记录,下面的代码将记录特定对象的函数调用。您甚至可以修改对象原型,以便所有新实例也都可以记录日志。我使用Object.getOwnPropertyNames代替for ... in,因此它可用于ECMAScript 6类,该类没有可枚举的方法。

function inject(obj, beforeFn) {
    for (let propName of Object.getOwnPropertyNames(obj)) {
        let prop = obj[propName];
        if (Object.prototype.toString.call(prop) === '[object Function]') {
            obj[propName] = (function(fnName) {
                return function() {
                    beforeFn.call(this, fnName, arguments);
                    return prop.apply(this, arguments);
                }
            })(propName);
        }
    }
}

function logFnCall(name, args) {
    let s = name + '(';
    for (let i = 0; i < args.length; i++) {
        if (i > 0)
            s += ', ';
        s += String(args[i]);
    }
    s += ')';
    console.log(s);
}

inject(Foo.prototype, logFnCall);

-1

这是一些Javascript替代,它将console.log添加到Javascript中的每个函数;在Regex101

$re = "/function (.+)\\(.*\\)\\s*\\{/m"; 
$str = "function example(){}"; 
$subst = "$& console.log(\"$1()\");"; 
$result = preg_replace($re, $subst, $str);

这是一个“快速而肮脏的hack”,但我发现它对于调试很有用。如果您有很多功能,请当心,因为这会增加很多代码。另外,RegEx很简单,可能不适用于更复杂的函数名称/声明。


-10

实际上,您可以将自己的函数附加到console.log上,以加载所有内容。

console.log = function(msg) {
    // Add whatever you want here
    alert(msg); 
}

2
正确与否,它不能回答问题。完全没有 (
以防
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.