自动将console.log添加到每个函数

时间:2011-02-17 19:51:42

标签: javascript function logging hook

有没有办法让任何函数在通过在某处注册一个全局钩子(也就是说,不修改实际函数本身)或通过其他方法调用它时调用console.log语句?

6 个答案:

答案 0 :(得分:60)

这是一种使用您选择的功能扩充全局命名空间中的所有函数的方法:

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后没有创建任何函数会产生额外的行为。

答案 1 :(得分:5)

记录函数调用的代理方法

有一种使用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"

check that this actually works in Codepen


请记住,使用Proxy可以为您提供比仅记录控制台名称更多的功能。

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

答案 2 :(得分:1)

如果您想要更有针对性的日志记录,以下代码将记录特定对象的函数调用。您甚至可以修改Object原型,以便所有新实例也可以进行日志记录。我使用Object.getOwnPropertyNames而不是for ...,因此它适用于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);

答案 3 :(得分:1)

对于我来说,这似乎是最优雅的解决方案:

/etc/X11/xorg.conf

答案 4 :(得分:0)

这里有一些Javascript代替了将Javascript中的每个函数添加到console.log中;在Regex101上播放:

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

这是一个快速而又肮脏的黑客攻击&#39;但我发现它对调试很有用。如果你有很多功能,请注意,因为这会添加很多代码。此外,RegEx很简单,可能不适用于更复杂的函数名称/声明。

答案 5 :(得分:-7)

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

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