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?
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?
Jawaban:
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 augment
akan memiliki perilaku tambahan.
fn.apply(this, arguments);
menjadireturn fn.apply(this, arguments);
return
ke fungsi paling dalam.
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);
};
}());
Ada cara baru menggunakan Proxy untuk mencapai fungsi ini di JS. berasumsi bahwa kita ingin memiliki console.log
fungsi 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 Proxy
memberi Anda lebih banyak fungsi daripada hanya mencatat nama konsol.
Juga metode ini berfungsi di Node.js juga.
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);
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.
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);
}