すべての関数にconsole.logを自動的に追加する


97

グローバルフックをどこかに(つまり、実際の関数自体を変更せずに)登録することによって、または他の方法で呼び出されたときに、関数にconsole.logステートメントを出力させる方法はありますか?


すばらしい質問です。これが可能かどうか知りたいのですが、不可能ではないでしょう...お気に入りのブラウザのjsエンジンに追加する機能リクエストを追加しますか?:-)
エンドファージ2011

完璧な質問、私はこのような何かが必要です
mjimcua

回答:


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しかし、この1つはありません:jsfiddle.net/Shawn/WnJQ5/1は私はありませんが、必ずそれはすべてのケースで動作します...違いが変化しているfn.apply(this, arguments);return fn.apply(this, arguments);
ショーン

2
@Shawn @SunnyShah修正済み。return最も内側の関数にaを追加するだけです。
ウェイン

ほぼ正常に動作しますが、このjquery:call:if(jQuery.isFunction(lSrc))でエラーが発生し、次のように表示されます:TypeError:jQuery.isFunction is not a function
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

関数呼び出しを記録するプロキシメソッド

JSでこの機能を実現するためにプロキシを使用する新しい方法があります。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でも機能し ます。


インスタンスとクラスを使用せずにこれを行うこともできますか?特にnode.jsで言えば?
Revadike

@Revadikeこれは役立つはずです:stackoverflow.com/a/28708700/5284370
Soorena

1

よりターゲットを絞ったロギングが必要な場合、次のコードは特定のオブジェクトの関数呼び出しを記録します。オブジェクトのプロトタイプを変更して、すべての新しいインスタンスがログを記録するようにすることもできます。for ... inではなくObject.getOwnPropertyNamesを使用したため、列挙可能なメソッドを持たない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);

それは「素早い汚いハック」ですが、デバッグに役立ちます。多くの関数がある場合、これは多くのコードを追加するので注意してください。また、RegExは単純で、より複雑な関数名/宣言では機能しない可能性があります。


-10

ロードするすべての内容について、実際にconsole.logに独自の関数をアタッチできます。

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

2
正しいかどうか、それは質問に答えません。まったく。(だれかがまだ混乱している場合)
redfox05 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.