Подтвердить что ты не робот

Как получить вызовы функции Javascript/трассировка во время выполнения

Когда я взаимодействую с моим приложением на основе AJAX на RUNTIME, я бы хотел, чтобы консоль выдала все функции, которые он вызывает. (так что нет трассировки стека, точек останова или профилирования или чего-либо еще)

Итак, скажем, я нажал кнопку на странице. Я бы хотел, чтобы он возвращал все функции прошло, когда это произошло:

Итак, я видел в консоли что-то вроде (когда я нажимал кнопку):

1. button1Clicked();
2.     calculating();
3.          printingResults();

Что в основном означает, что button1Clicked() вызвал вычисление(), которое вызвало printingResults()

Есть ли утилита или плагин, браузер или, может быть, какой-то способ на этом языке? Я использую google chrome, btw.

p.s и NO Я не хочу проходить через каждую функцию и добавлять "console.log("inside function X")" b/c, что слишком много работает

p.p.s в качестве дополнительного бонуса, я бы тоже хотел увидеть аргументы, передаваемые в функции, но, возможно, это нажатие.: >

4b9b3361

Ответ 1

Я не могу придумать отличный способ перехватить все вызовы функций глобально, чтобы вставить ведение журнала (хотя в разделе обновления есть подходящее обходное решение).

Вместо этого, как насчет только добавления ведения журнала к функциям в определенном пространстве имен, которое вас волнует? Вы можете сделать это со следующим установочным кодом:

var functionLogger = {};

functionLogger.log = true;//Set this to false to disable logging 

/**
 * Gets a function that when called will log information about itself if logging is turned on.
 *
 * @param func The function to add logging to.
 * @param name The name of the function.
 *
 * @return A function that will perform logging and then call the function. 
 */
functionLogger.getLoggableFunction = function(func, name) {
    return function() {
        if (functionLogger.log) {
            var logText = name + '(';

            for (var i = 0; i < arguments.length; i++) {
                if (i > 0) {
                    logText += ', ';
                }
                logText += arguments[i];
            }
            logText += ');';

            console.log(logText);
        }

        return func.apply(this, arguments);
    }
};

/**
 * After this is called, all direct children of the provided namespace object that are 
 * functions will log their name as well as the values of the parameters passed in.
 *
 * @param namespaceObject The object whose child functions you'd like to add logging to.
 */
functionLogger.addLoggingToNamespace = function(namespaceObject){
    for(var name in namespaceObject){
        var potentialFunction = namespaceObject[name];

        if(Object.prototype.toString.call(potentialFunction) === '[object Function]'){
            namespaceObject[name] = functionLogger.getLoggableFunction(potentialFunction, name);
        }
    }
};

Затем для любого объекта namespaceObject, к которому вы хотите добавить запись, вы просто вызываете:

functionLogger.addLoggingToNamespace(yourNamespaceObject);

Здесь скрипка, чтобы увидеть ее в действии.

UPDATE
Обратите внимание, что вы можете вызвать functionLogger.addLoggingToNamespace(window);, чтобы добавить журнал во все глобальные функции во время вызова. Кроме того, если вы действительно хотите, вы можете пройти дерево, чтобы найти какие-либо функции и соответствующим образом обновить их. Единственным недостатком этого метода является то, что он работает только с функциями, которые существуют в то время. Таким образом, это все еще не самое большое решение, но это намного меньше, чем добавление записей вручную:)

Ответ 2

Это называется профилированием, а Chrome и Firebug встроены. В Инструменты разработчика Chrome перейдите на вкладку профилей и нажмите запись ( круг). Выполните свой аякс и после вашего ответа нажмите кнопку записи еще раз, чтобы остановить. Результаты профилирования появятся в правой панели.

Обратите внимание, что это даст вам все, поэтому, если вы используете библиотеку jQuery, подавляющее большинство вызовов функций будет для вас мусором. Я пробовал это несколько раз, и я считаю, что сделать console.log('inside <method>') гораздо полезнее.

Ответ 3

Попробуйте diyism_trace_for_javascript.htm:

https://code.google.com/p/diyism-trace/downloads/list

eval('window.c=function(){3+5;}');
declare_ticks_for(window);

function a(k, c) {
  return k + 2;
}

function b() {
  4 + 3;
  a(3, {'a':'c','b':'d'});
  c();
  return 5 + 4;
}

b();

Просмотр журналов на вкладке консоли хром или firefox

Ответ 4

Возможно, у вас есть JavaScript, который может выполнить некоторые действия по добавлению console.log для вас:

Автоматическое добавление console.log для каждой функции

Также этот блог Paul Irish может помочь:

http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/

Он включает ссылку на какой-то JavaScript, специально предназначенный для протоколирования аргументов:

http://pastie.org/1033665

Ответ 5

Вариант решения Briguy37, я написал тот, который принимает функцию для вызова перед каждым методом. Он также работает с классами ECMAScript 6, где методы не перечислены для... in. Я использую его для изменения прототипов объекта, чтобы добавить ведение журнала ко всем новым экземплярам моего объекта.

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

Ответ 6

Я использовал решение @Briguy37 с улучшением. В моем случае я не хотел отслеживать функции из некоторых библиотек, поэтому я добавил код, чтобы их исключить. Вот как он используется:

  • Сначала включите определение функций, которые вы не хотите отслеживать;
  • excludeLoggingToNamespace, чтобы перечислять функции, определенные до сих пор, и исключать их;
  • Включить определение функций, которые вы хотите отслеживать;
  • Вызовите addLoggingToNamespace, чтобы добавить возможности ведения журнала к функциям, определенным на предыдущем шаге.

Пример:

<script src="js/someLibrary.js"></script>
<script>
    functionLogger.excludeLoggingToNamespace(window);
</script>
<script src="js/codeIWantToTraceHere.js"></script>
<script>
    functionLogger.addLoggingToNamespace(window);
</script>

Вот код, который я добавил в решение @Briguy37:

var excludedFunctions = {};

        functionLogger.excludeLoggingToNamespace = function(namespaceObject){
            for(var name in namespaceObject){
                var potentialFunction = namespaceObject[name];

                if(Object.prototype.toString.call(potentialFunction) === '[object Function]') {
                    excludedFunctions[name] = name;
                }
            }
        }; 

И мне пришлось модифицировать метод @Bigigy37 addLoggingToNamespace, чтобы принять хэш хэш excludedFunctions:

functionLogger.addLoggingToNamespace = function(namespaceObject){
    for(var name in namespaceObject){
        var potentialFunction = namespaceObject[name];

        if(Object.prototype.toString.call(potentialFunction) === '[object Function]' && 
           !excludedFunctions[name]) {
            namespaceObject[name] = functionLogger.getLoggableFunction(potentialFunction, name);
        }
    }
};