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

JRL*_*JRL 90 javascript hook logging function

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

Way*_*ett 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);
});
Run Code Online (Sandbox Code Playgroud)

一个缺点是,调用后创建的函数augment不会有其他行为.

  • 此解决方案不使用jQuery (4认同)
  • @SunnyShah不,它不是:http://jsfiddle.net/Shawn/WnJQ5/但是这个确实:http://jsfiddle.net/Shawn/WnJQ5/1/虽然我不确定它是否适用于所有case ...区别在于改变`fn.apply(this,arguments);`返回`fn.apply(this,arguments);` (2认同)
  • @Shawn @SunnyShah修正了.只需要在最里面的函数中添加一个`return`. (2认同)

Ser*_*ell 17

对我来说,这看起来是最优雅的解决方案:

(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);
    };
}());
Run Code Online (Sandbox Code Playgroud)


Soo*_*ena 6

记录函数调用的代理方法

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

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

const foo = new TestClass()
foo.a() // nothing get logged
Run Code Online (Sandbox Code Playgroud)

我们可以使用覆盖该类每个属性的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"
Run Code Online (Sandbox Code Playgroud)

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


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

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