Gibt es eine Möglichkeit, eine Funktion dazu zu bringen, eine console.log-Anweisung auszugeben, wenn sie aufgerufen wird, indem irgendwo ein globaler Hook registriert wird (dh ohne die eigentliche Funktion selbst zu ändern) oder auf andere Weise?
Gibt es eine Möglichkeit, eine Funktion dazu zu bringen, eine console.log-Anweisung auszugeben, wenn sie aufgerufen wird, indem irgendwo ein globaler Hook registriert wird (dh ohne die eigentliche Funktion selbst zu ändern) oder auf andere Weise?
Antworten:
Hier ist eine Möglichkeit, alle Funktionen im globalen Namespace mit der Funktion Ihrer Wahl zu erweitern:
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);
});
Ein Nachteil ist, dass keine nach dem Aufruf erstellten Funktionen augment
das zusätzliche Verhalten aufweisen.
fn.apply(this, arguments);
zureturn fn.apply(this, arguments);
return
innersten Funktion hinzugefügt werden.
Für mich scheint dies die eleganteste Lösung zu sein:
(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);
};
}());
Es gibt eine neue Möglichkeit, Proxy zu verwenden, um diese Funktionalität in JS zu erreichen. Nehmen wir an, wir möchten eine haben, console.log
wenn eine Funktion einer bestimmten Klasse aufgerufen wird:
class TestClass {
a() {
this.aa = 1;
}
b() {
this.bb = 1;
}
}
const foo = new TestClass()
foo.a() // nothing get logged
Wir können unsere Klasseninstanziierung durch einen Proxy ersetzen, der jede Eigenschaft dieser Klasse überschreibt. so:
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"
Überprüfen Sie, ob dies in Codepen tatsächlich funktioniert
Denken Proxy
Sie daran, dass die Verwendung viel mehr Funktionen bietet, als nur Konsolennamen zu protokollieren.
Auch diese Methode funktioniert in Node.js auch.
Wenn Sie eine gezieltere Protokollierung wünschen, protokolliert der folgende Code Funktionsaufrufe für ein bestimmtes Objekt. Sie können sogar Objektprototypen so ändern, dass auch alle neuen Instanzen protokolliert werden. Ich habe Object.getOwnPropertyNames anstelle von for ... in verwendet, daher funktioniert es mit ECMAScript 6-Klassen, die keine aufzählbaren Methoden haben.
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);
Hier ist etwas Javascript, das das Hinzufügen von console.log zu jeder Funktion in Javascript ersetzt. Spielen Sie damit auf Regex101 :
$re = "/function (.+)\\(.*\\)\\s*\\{/m";
$str = "function example(){}";
$subst = "$& console.log(\"$1()\");";
$result = preg_replace($re, $subst, $str);
Es ist ein "schneller und schmutziger Hack", aber ich finde ihn nützlich zum Debuggen. Wenn Sie viele Funktionen haben, achten Sie darauf, dass dadurch viel Code hinzugefügt wird. Außerdem ist RegEx einfach und funktioniert möglicherweise nicht für komplexere Funktionsnamen / Deklarationen.
Sie können Ihre eigene Funktion für alles, was geladen wird, an console.log anhängen.
console.log = function(msg) {
// Add whatever you want here
alert(msg);
}