Aggiunta automatica di console.log a ogni funzione


97

C'è un modo per fare in modo che qualsiasi funzione emetta un'istruzione console.log quando viene chiamata registrando un hook globale da qualche parte (cioè senza modificare la funzione stessa) o tramite altri mezzi?


domanda eccellente, mi piacerebbe sapere se è possibile ma sono abbastanza sicuro che non lo sia ... Forse aggiungere una richiesta di funzionalità per aggiungerla nel motore js del tuo browser preferito? :-)
Endophage

Domanda perfetta, ho bisogno di qualcosa di simile come questo
mjimcua

Risposte:


62

Ecco un modo per aumentare tutte le funzioni nello spazio dei nomi globale con la funzione di tua scelta:

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);
});

Uno svantaggio è che nessuna funzione creata dopo la chiamata augmentavrà il comportamento aggiuntivo.


Gestisce correttamente i valori di ritorno della funzione?
SunnyShah

2
@SunnyShah No, non è così: jsfiddle.net/Shawn/WnJQ5 Ma questo : jsfiddle.net/Shawn/WnJQ5/1 anche se non sono sicuro che funzionerà in TUTTI i casi ... La differenza sta cambiando fn.apply(this, arguments);inreturn fn.apply(this, arguments);
Shawn

2
@Shawn @SunnyShah Risolto. Avevo solo bisogno di aggiungere una returnalla funzione più interna.
Wayne

funziona quasi bene ma ricevo un errore con questo jquery: call: if (jQuery.isFunction (lSrc)) e dice: TypeError: jQuery.isFunction non è una funzione
fekiri malek

4
Questa soluzione non utilizza jQuery
Wayne

8

Quanto a me, questa sembra la soluzione più 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);
    };
}());

7

Metodo proxy per registrare le chiamate di funzioni

C'è un nuovo modo di utilizzare Proxy per ottenere questa funzionalità in JS. supponiamo di voler avere un console.logogni volta che viene chiamata una funzione di una classe specifica:

class TestClass {
  a() {
    this.aa = 1;
  }
  b() {
    this.bb = 1;
  }
}

const foo = new TestClass()
foo.a() // nothing get logged

possiamo sostituire la nostra istanza di classe con un proxy che sovrascrive ogni proprietà di questa classe. così:

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"

controlla che funzioni effettivamente in Codepen


Ricorda che l'utilizzo Proxyti offre molte più funzionalità rispetto alla semplice registrazione dei nomi delle console.

Anche questo metodo funziona in Node.js troppo.


Puoi farlo anche senza usare istanze e classi? In particolare parlando in node.js?
Revadike

@Revadike Questo dovrebbe aiutare: stackoverflow.com/a/28708700/5284370
Soorena

1

Se si desidera una registrazione più mirata, il codice seguente registrerà le chiamate di funzione per un particolare oggetto. Puoi anche modificare i prototipi di oggetti in modo che anche tutte le nuove istanze vengano registrate. Ho usato Object.getOwnPropertyNames invece di per ... in, quindi funziona con le classi ECMAScript 6, che non hanno metodi enumerabili.

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);

-1

Ecco alcuni Javascript che sostituiscono aggiunge console.log a ogni funzione in Javascript; Gioca con esso su Regex101 :

$re = "/function (.+)\\(.*\\)\\s*\\{/m"; 
$str = "function example(){}"; 
$subst = "$& console.log(\"$1()\");"; 
$result = preg_replace($re, $subst, $str);

È un "trucco rapido e sporco" ma lo trovo utile per il debug. Se hai molte funzioni, fai attenzione perché questo aggiungerà molto codice. Inoltre, la RegEx è semplice e potrebbe non funzionare per nomi / dichiarazioni di funzioni più complesse.


-10

Puoi effettivamente collegare la tua funzione a console.log per tutto ciò che viene caricato.

console.log = function(msg) {
    // Add whatever you want here
    alert(msg); 
}

2
corretto o no, non risponde alla domanda. affatto. (nel caso qualcuno fosse ANCORA confuso)
redfox05
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.