Пользовательская функция журнала консоли, оболочка console.log
function log( msgOrObj ){
if(dev_mode){
console.log({
'message': msgOrObj,
'caller': arguments.callee.caller.toString()
});
}
}
Итак, я попытался написать простую пользовательскую функцию журнала консоли (как описано выше). Однако я изо всех сил пытаюсь найти, из какого файла и строки пришел вызывающий. Максимум, что я могу видеть, - это функция, которая его вызывает.
Кто-нибудь делал что-нибудь подобное? Или это вообще возможно?
пример, используемый в somescript.js из строки 70:
log('some very important message!')
8 ответов
Итак, вот что я сделал в конце (где функция shout - это функция, выполняемая только в режиме разработки):
function log( msgOrObj ){
if(dev_mode){
if( typeof(window.console) != 'undefined' ){
try { invalidfunctionthrowanerrorplease(); }
catch(err) { var logStack = err.stack; }
var fullTrace = logStack.split('\n');
for( var i = 0 ; i < fullTrace.length ; ++i ){
fullTrace[i] = fullTrace[i].replace(/\s+/g, ' ');
}
var caller = fullTrace[1],
callerParts = caller.split('@'),
line = '';
//CHROME & SAFARI
if( callerParts.length == 1 ){
callerParts = fullTrace[2].split('('), caller = false;
//we have an object caller
if( callerParts.length > 1 ){
caller = callerParts[0].replace('at Object.','');
line = callerParts[1].split(':');
line = line[2];
}
//called from outside of an object
else {
callerParts[0] = callerParts[0].replace('at ','');
callerParts = callerParts[0].split(':');
caller = callerParts[0]+callerParts[1];
line = callerParts[2];
}
}
//FIREFOX
else {
var callerParts2 = callerParts[1].split(':');
line = callerParts2.pop();
callerParts[1] = callerParts2.join(':');
caller = (callerParts[0] == '') ? callerParts[1] : callerParts[0];
}
console.log( ' ' );
console.warn( 'Console log: '+ caller + ' ( line '+ line +' )' );
console.log( msgOrObj );
console.log({'Full trace:': fullTrace });
console.log( ' ' );
} else {
shout('This browser does not support console.log!')
}
}
}
log (), если он объявлен до того, как остальная часть приложения может быть вызвана из любой точки приложения, и предоставит разработчику всю необходимую информацию, плюс не выйдет из режима разработки.
( http://webconfiguration.blogspot.co.uk/2013/12/javascript-console-log-wrapper-with.html)
Да, но он очень хакерский и не защищен от браузера. Вы можете использовать это в качестве отправной точки. Это заимствует из этого ответа.
window.trace = function stackTrace() {
var err = new Error();
return err.stack;
}
window.my_log = function (x) {
var line = trace();
var lines = line.split("\n");
console.log(x + " " + lines[2].substring(lines[2].indexOf("("), lines[2].lastIndexOf(")") + 1))
}
window.my_log("What light through yonder window breaks?")
Производит:
What light through yonder window breaks? (<anonymous>:2:42)
Единственный способ, которым я видел надежное извлечение информации такого рода, - это выдать ошибку, а затем извлечь информацию о вызывающем абоненте из трассировки стека, что-то вроде:
function log( msgOrObj ){
if(dev_mode){
try {
in_val_id(); // force an error by calling an non-existent method
catch(err) {
// some regex/string manipulation here to extract function name
// line num, etc. from err.stack
var caller = ...
var lineNo = ...
}
console.log({
'message': msgOrObj,
'caller': caller,
'lineNo': lineNo
});
}
}
Стек в Chrome находится в этой форме:
ReferenceError: in_val_id is not defined
at log (<anonymous>:4:13)
at <anonymous>:2:14
at <anonymous>:2:28
at Object.InjectedScript._evaluateOn (<anonymous>:581:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:540:52)
at Object.InjectedScript.evaluate (<anonymous>:459:21)
Вы можете извлечь имя функции с помощью:
caller = err.stack.split('\n')[3].split('at ')[1].split(' (')[0];
использование регулярных выражений здесь может быть более производительным. Вероятно, вам понадобятся разные подходы для извлечения этой информации в разных браузерах.
Слово предупреждения, хотя; выбрасывать и обрабатывать ошибки дорого, поэтому вывод большого количества сообщений журнала таким образом, вероятно, повлияет на общую производительность, хотя это может быть приемлемо, если это специально для режима отладки.
Я использую это в Node, и это особенно эффективно. Console.log - это просто функция, которую можно переназначить, а также сохранить для безопасного хранения и вернуть обратно после того, как мы закончим. У меня нет причин полагать, что это не сработает и в браузере.
//Store console.log function in an object so
//we can still use it.
theConsole = {};
theConsole.log = console.log;
//This function is called when console.log occurs
//arguments[0] is what would normally be printed.
console.log = function(){
theConsole.log(">" + arguments[0]);
}
//Call our console.log wrapper
console.log("Testing testing 123");
console.log("Check one two");
//Put back the way it was
console.log = theConsole.log;
console.log("Now normal");
Вместо использования аргументов вы можете сделать
function log( msg ) {
if (dev_mode) {
var e = new Error(msg);
console.log(e.stack);
}
}
Это покажет вам порядок, в котором были вызваны все функции (включая номера строк и файлы). Вы можете просто проигнорировать первые 2 строки стека (одна будет содержать сообщение об ошибке, а другая будет содержать функцию log, поскольку вы создаете объект ошибки внутри функции).
Если вы хотите более надежное ведение журнала - используйте соответствующую оболочку для console.log с правильным номером строки? как предложил @DoXicK
Есть несколько вариантов, чтобы быстро пойти по этому поводу.
1 - Использование console.error Не очень удобно, реальные ошибки останутся незамеченными, и появление большого количества красного на выходных данных вашей консоли может отрицательно повлиять на ваш моральный дух. Короче говоря - не используйте, если это не для очень маленького сценария или некоторого теста
2 - Добавьте свой метод log к прототипу Object, чтобы получить текущую область видимости / имя модуля / и т. Д. Гораздо более гибкий и элегантный.
Object.prototype.log = function(message){
console.log({
'message': message,
'caller': this,
'stack':arguments.callee.caller.toString()
});
};
Используйте (где угодно) как:
this.log("foo");
Вы можете добавить методы из этого потока, чтобы получить точное имя функции внутри вашего объекта, например:
var callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 9, callerFunc.indexOf("(")) || "anoynmous");
Тем не менее, убедитесь, что ваша область названа... заставляя вас идти от этого:
Module.method = function(){}
К этому:
Module.method = function method(){}
Что касается номеров строк, вызов (new Error()) даст вам доступ к номеру строки, по которому он был вызван - и даже не во всех браузерах.
Создание элегантной функции отладки - это работа
Как бы мне не хотелось это признавать, другой ответ, предполагающий повторные опыты по результатам попытки, кажется, быстрее вылечит вашу проблему.
Попробуй это
window.log = (() => {
if (dev_mode) {
return console.log;
} else return () => {};
})();
Кажется, вы слишком много боретесь. У меня есть простое однострочное решение:-
//Just do this, that I have done below: HAVE FUN
var log=console.log;
log(`So this way is known as Aniket's way.`);
log(`Don't be too serious this is just the fun way of doing same thing`);
log(`Thank You`)