簡體   English   中英

自動將 console.log 添加到每個函數

[英]Adding console.log to every function automatically

當通過在某處注冊全局鈎子(即,不修改實際函數本身)或通過其他方式調用任何函數時,有沒有辦法使任何函數輸出 console.log 語句?

這是一種使用您選擇的函數來擴充全局命名空間中的所有函數的方法:

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將有額外的行為。

對我來說,這看起來是最優雅的解決方案:

(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);
    };
}());

記錄函數調用的代理方法

在 JS 中有一種使用Proxy實現此功能的新方法。 假設我們希望在調用特定類的函數時有一個console.log

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

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

我們可以用覆蓋這個類的每個屬性的代理替換我們的類實例化。 所以:

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。

如果您想要更有針對性的日志記錄,以下代碼將記錄特定對象的函數調用。 您甚至可以修改對象原型,以便所有新實例也可以記錄。 我使用了 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);

這是一些 Javascript,它取代了將 console.log 添加到 Javascript 中的每個函數; Regex101上玩它:

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

這是一個“快速而骯臟的黑客”,但我發現它對調試很有用。 如果你有很多函數,要小心,因為這會增加很多代碼。 此外,RegEx 很簡單,可能不適用於更復雜的函數名稱/聲明。

對於加載的所有內容,您實際上可以將自己的函數附加到 console.log。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM