Додавання console.log до кожної функції автоматично


97

Чи є спосіб змусити будь-яку функцію вивести оператор console.log, коли він викликається, зареєструвавши десь глобальний хук (тобто, не змінюючи саму фактичну функцію) або якимось іншим способом?


чудове запитання, я хотів би знати, чи можливо це, але я впевнений, що це не так ... Може, додати запит на функцію, щоб він був доданий в js-движок для вашого улюбленого браузера? :-)
Ендофаг

Ідеальне запитання, мені потрібно щось подібне
mjimcua

Відповіді:


62

Ось спосіб збільшити всі функції у глобальному просторі імен за допомогою вибраної вами функції:

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

З іншого боку, жодна функція, створена після виклику, augmentне матиме додаткової поведінки.


Чи правильно він обробляє повернені значення функції?
SunnyShah

2
@SunnyShah Ні, це не так: jsfiddle.net/Shawn/WnJQ5 Але цей робить: jsfiddle.net/Shawn/WnJQ5/1, хоча я не впевнений, що це спрацює у ВСІХ випадках ... Різниця змінюється fn.apply(this, arguments);наreturn fn.apply(this, arguments);
Shawn

2
@Shawn @SunnyShah Виправлено. Просто потрібно було додати a returnдо внутрішньої функції.
Wayne

працює майже нормально, але я отримую помилку з цим jquery: call: if (jQuery.isFunction (lSrc)) і в ньому написано: TypeError: jQuery.isFunction не є функцією
fekiri malek

4
Це рішення не використовує jQuery
Уейн

8

Як на мене, це виглядає як найелегантніше рішення:

(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

Метод проксі для реєстрації викликів функцій

Існує новий спосіб використання Proxy для досягнення цієї функціональності в JS. припустимо, що ми хочемо мати console.logщоразу, коли викликається функція певного класу:

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

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

ми можемо замінити наш екземпляр класу на Proxy, який замінює кожну властивість цього класу. так:

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"

переконайтесь, що це насправді працює в Codepen


Пам'ятайте, що використання Proxyдає вам набагато більше функціональних можливостей, ніж просто реєстрація імен консолі.

Крім того, цей метод працює в Node.js теж.


Чи можете ви це зробити, не використовуючи екземпляри та класи? Конкретно кажучи в node.js?
Ревадіке

@Revadike це повинно допомогти: stackoverflow.com/a/28708700/5284370
Soorena

1

Якщо ви хочете більш цілеспрямований журнал, наступний код буде реєструвати виклики функцій для певного об'єкта. Ви навіть можете змінити прототипи об’єктів, щоб усі нові екземпляри також отримували журнал. Я використовував Object.getOwnPropertyNames замість for ... in, тому він працює з ECMAScript 6 класами, які не мають перелічених методів.

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

Ось Javascript, який замінює додавання console.log до кожної функції Javascript; Пограйте з ним на Regex101 :

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

Це "швидкий і брудний хак", але я вважаю це корисним для налагодження. Якщо у вас багато функцій, будьте обережні, оскільки це додасть багато коду. Крім того, RegEx простий і може не працювати для більш складних імен / оголошень функцій.


-10

Ви можете приєднати власну функцію до console.log для всього, що завантажується.

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

2
правильно чи ні, це не відповідає на питання. зовсім. (якщо хтось ще
БУДЕ ПУТИНИМ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.