¿Hay alguna manera de hacer que una función genere una declaración console.log cuando se llama registrando un gancho global en algún lugar (es decir, sin modificar la función real) o por algún otro medio?
¿Hay alguna manera de hacer que una función genere una declaración console.log cuando se llama registrando un gancho global en algún lugar (es decir, sin modificar la función real) o por algún otro medio?
Respuestas:
Esta es una forma de aumentar todas las funciones en el espacio de nombres global con la función que elija:
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);
});
Una desventaja es que ninguna función creada después de la llamada augment
tendrá el comportamiento adicional.
fn.apply(this, arguments);
areturn fn.apply(this, arguments);
return
a la función más interna.
En cuanto a mí, esta parece la solución más 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);
};
}());
Hay una nueva forma de usar Proxy para lograr esta funcionalidad en JS. Supongamos que queremos tener un console.log
siempre que se llame a una función de una clase específica:
class TestClass {
a() {
this.aa = 1;
}
b() {
this.bb = 1;
}
}
const foo = new TestClass()
foo.a() // nothing get logged
podemos reemplazar la instanciación de nuestra clase con un Proxy que anule cada propiedad de esta clase. entonces:
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"
compruebe que esto realmente funciona en Codepen
Recuerde que el uso Proxy
le brinda muchas más funciones que solo registrar nombres de consola.
Además, este método funciona en Node.js también.
Si desea un registro más específico, el siguiente código registrará las llamadas a funciones para un objeto en particular. Incluso puede modificar los prototipos de objetos para que todas las instancias nuevas también se registren. Usé Object.getOwnPropertyNames en lugar de para ... in, por lo que funciona con las clases ECMAScript 6, que no tienen métodos enumerables.
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);
Aquí hay algo de Javascript que reemplaza agrega console.log a cada función en Javascript; Juega con él en Regex101 :
$re = "/function (.+)\\(.*\\)\\s*\\{/m";
$str = "function example(){}";
$subst = "$& console.log(\"$1()\");";
$result = preg_replace($re, $subst, $str);
Es un 'truco rápido y sucio' pero lo encuentro útil para depurar. Si tiene muchas funciones, tenga cuidado porque esto agregará mucho código. Además, la expresión regular es simple y es posible que no funcione para declaraciones o nombres de funciones más complejos.
De hecho, puede adjuntar su propia función a console.log para todo lo que se carga.
console.log = function(msg) {
// Add whatever you want here
alert(msg);
}