Existe-t-il un moyen de faire en sorte qu'une fonction génère une instruction console.log lorsqu'elle est appelée en enregistrant un hook global quelque part (c'est-à-dire sans modifier la fonction elle-même) ou via un autre moyen?
Existe-t-il un moyen de faire en sorte qu'une fonction génère une instruction console.log lorsqu'elle est appelée en enregistrant un hook global quelque part (c'est-à-dire sans modifier la fonction elle-même) ou via un autre moyen?
Réponses:
Voici un moyen d'augmenter toutes les fonctions de l'espace de noms global avec la fonction de votre choix:
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);
});
Un inconvénient est qu'aucune fonction créée après l'appel augment
n'aura le comportement supplémentaire.
fn.apply(this, arguments);
enreturn fn.apply(this, arguments);
return
à la fonction la plus profonde.
Quant à moi, cela ressemble à la solution la plus élégante:
(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);
};
}());
Il existe une nouvelle façon d'utiliser Proxy pour obtenir cette fonctionnalité dans JS. supposons que nous voulons avoir une console.log
chaque fois qu'une fonction d'une classe spécifique est appelée:
class TestClass {
a() {
this.aa = 1;
}
b() {
this.bb = 1;
}
}
const foo = new TestClass()
foo.a() // nothing get logged
nous pouvons remplacer notre instanciation de classe par un proxy qui remplace chaque propriété de cette classe. alors:
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"
vérifier que cela fonctionne réellement dans Codepen
N'oubliez pas que l'utilisation Proxy
vous offre beaucoup plus de fonctionnalités que la simple journalisation des noms de console.
De plus , cette méthode fonctionne en Node.js aussi.
Si vous souhaitez une journalisation plus ciblée, le code suivant consignera les appels de fonction pour un objet particulier. Vous pouvez même modifier les prototypes d'objets afin que toutes les nouvelles instances soient également enregistrées. J'ai utilisé Object.getOwnPropertyNames au lieu de for ... in, donc cela fonctionne avec les classes ECMAScript 6, qui n'ont pas de méthodes énumérables.
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);
Voici du Javascript qui remplace ajoute console.log à chaque fonction en Javascript; Jouez avec sur Regex101 :
$re = "/function (.+)\\(.*\\)\\s*\\{/m";
$str = "function example(){}";
$subst = "$& console.log(\"$1()\");";
$result = preg_replace($re, $subst, $str);
C'est un «hack rapide et sale» mais je le trouve utile pour le débogage. Si vous avez beaucoup de fonctions, méfiez-vous car cela ajoutera beaucoup de code. En outre, le RegEx est simple et peut ne pas fonctionner pour des noms / déclarations de fonctions plus complexes.
Vous pouvez en fait attacher votre propre fonction à console.log pour tout ce qui se charge.
console.log = function(msg) {
// Add whatever you want here
alert(msg);
}