Menambahkan console.log ke setiap fungsi secara otomatis


97

Apakah ada cara untuk membuat fungsi mengeluarkan pernyataan console.log ketika dipanggil dengan mendaftarkan hook global di suatu tempat (yaitu, tanpa mengubah fungsi sebenarnya itu sendiri) atau melalui cara lain?


pertanyaan yang sangat bagus, saya ingin tahu apakah ini mungkin tetapi saya cukup yakin itu tidak ... Mungkin menambahkan permintaan fitur untuk ditambahkan di mesin js untuk browser favorit Anda? :-)
Endophage

Pertanyaan yang tepat, saya butuh sesuatu yang serupa seperti ini
mjimcua

Jawaban:


62

Berikut cara untuk menambah semua fungsi di namespace global dengan fungsi pilihan Anda:

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

Satu sisi negatifnya adalah bahwa tidak ada fungsi yang dibuat setelah pemanggilan augmentakan memiliki perilaku tambahan.


Apakah itu menangani nilai kembalian fungsi dengan benar?
SunnyShah

2
@SunnyShah Tidak tidak: jsfiddle.net/Shawn/WnJQ5 Tapi yang ini: jsfiddle.net/Shawn/WnJQ5/1 meskipun saya tidak yakin ini akan berfungsi di SEMUA kasus ... Perbedaannya adalah berubah fn.apply(this, arguments);menjadireturn fn.apply(this, arguments);
Shawn

2
@Shawn @Shah Tetap. Hanya perlu menambahkan a returnke fungsi paling dalam.
Wayne

berfungsi hampir dengan baik tetapi saya mendapatkan kesalahan dengan jquery ini: call: if (jQuery.isFunction (lSrc)) dan dikatakan: TypeError: jQuery.isFunction bukanlah sebuah fungsi
fekiri malek

4
Solusi ini tidak menggunakan jQuery
Wayne

8

Bagi saya, ini terlihat seperti solusi paling elegan:

(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

Metode Proksi untuk mencatat panggilan Fungsi

Ada cara baru menggunakan Proxy untuk mencapai fungsi ini di JS. berasumsi bahwa kita ingin memiliki console.logfungsi kapan pun dari kelas tertentu dipanggil:

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

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

kita dapat mengganti instance kelas kita dengan Proxy yang mengganti setiap properti kelas ini. begitu:

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"

periksa apakah ini benar-benar berfungsi di Codepen


Ingatlah bahwa menggunakan Proxymemberi Anda lebih banyak fungsi daripada hanya mencatat nama konsol.

Juga metode ini berfungsi di Node.js juga.


Dapatkah Anda juga melakukan ini tanpa menggunakan instance dan kelas? Secara khusus berbicara di node.js?
Revadike

@Revadike ini akan membantu: stackoverflow.com/a/28708700/5284370
Soorena

1

Jika Anda ingin logging lebih bertarget, kode berikut akan mencatat panggilan fungsi untuk objek tertentu. Anda bahkan dapat memodifikasi prototipe Object sehingga semua instance baru juga dapat masuk. Saya menggunakan Object.getOwnPropertyNames dan bukan untuk ... in, jadi ia bekerja dengan kelas ECMAScript 6, yang tidak memiliki metode enumerable.

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

Berikut beberapa Javascript yang menggantikan menambahkan console.log ke setiap fungsi di Javascript; Mainkan di Regex101 :

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

Ini adalah 'peretasan cepat dan kotor' tetapi menurut saya berguna untuk debugging. Jika Anda memiliki banyak fungsi, berhati-hatilah karena ini akan menambah banyak kode. Selain itu, RegEx sederhana dan mungkin tidak berfungsi untuk nama / deklarasi fungsi yang lebih kompleks.


-10

Anda sebenarnya dapat melampirkan fungsi Anda sendiri ke console.log untuk semua yang dimuat.

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

2
benar atau tidak, itu tidak menjawab pertanyaan itu. sama sekali. (jika ada yang MASIH bingung)
redfox05
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.