Existe uma maneira de fazer com que qualquer função produza uma instrução console.log quando for chamada registrando um gancho global em algum lugar (isto é, sem modificar a função real em si) ou por algum outro meio?
Existe uma maneira de fazer com que qualquer função produza uma instrução console.log quando for chamada registrando um gancho global em algum lugar (isto é, sem modificar a função real em si) ou por algum outro meio?
Respostas:
Esta é uma maneira de aumentar todas as funções no namespace global com a função de sua escolha:
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);
});
Uma desvantagem é que nenhuma função criada após a chamada augment
terá o comportamento adicional.
fn.apply(this, arguments);
parareturn fn.apply(this, arguments);
return
à função mais interna.
Para mim, esta parece ser a solução mais elegante:
(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);
};
}());
Há uma nova maneira de usar o Proxy para obter essa funcionalidade em JS. suponha que queremos ter um console.log
sempre que uma função de uma classe específica for chamada:
class TestClass {
a() {
this.aa = 1;
}
b() {
this.bb = 1;
}
}
const foo = new TestClass()
foo.a() // nothing get logged
podemos substituir nossa instanciação de classe por um Proxy que substitui cada propriedade desta classe. tão:
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"
verifique se isso realmente funciona no Codepen
Lembre-se de que usar Proxy
oferece muito mais funcionalidade do que apenas registrar nomes de console.
Além disso, este método funciona em Node.js também.
Se você quiser um registro mais direcionado, o código a seguir registrará as chamadas de função para um objeto específico. Você pode até mesmo modificar protótipos de objeto para que todas as novas instâncias também obtenham registro. Usei Object.getOwnPropertyNames em vez de for ... in, então ele funciona com classes ECMAScript 6, que não têm métodos enumeráveis.
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);
Aqui estão alguns Javascript que substituem adiciona console.log a todas as funções em Javascript; Brinque com ele no Regex101 :
$re = "/function (.+)\\(.*\\)\\s*\\{/m";
$str = "function example(){}";
$subst = "$& console.log(\"$1()\");";
$result = preg_replace($re, $subst, $str);
É um 'hack rápido e sujo', mas acho útil para depuração. Se você tiver muitas funções, tome cuidado, pois isso adicionará muito código. Além disso, o RegEx é simples e pode não funcionar para nomes / declarações de funções mais complexas.
Na verdade, você pode anexar sua própria função ao console.log para tudo o que carrega.
console.log = function(msg) {
// Add whatever you want here
alert(msg);
}