function log( msgOrObj ){
if(dev_mode){
console.log({
'message': msgOrObj,
'caller': arguments.callee.caller.toString()
});
}
}
所以,我试图编写一个简单的自定义控制台日志功能(如上所述)。但是我很难找到调用者来自哪个文件和行。我能看到的最多就是调用它的函数。
有没有人做过类似的事情?或者这甚至可能吗?
第70行的somescript.js中使用的示例:
log('some very important message!')
答案 0 :(得分:4)
是的但它非常hacky并且不能跨浏览器安全。您可以将此作为起点。它borrows from this answer。
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)
答案 1 :(得分:3)
我看到可靠地提取这种信息的唯一方法是抛出一个错误,然后从堆栈跟踪中提取调用者信息,类似于:
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];
在这里使用正则表达式可能会更高效。您可能需要使用不同的方法来使用不同的浏览器提取此信息。
尽管有警告;抛出和处理错误是昂贵的,因此以这种方式输出大量日志消息可能会影响一般性能,但如果它专门用于调试模式则可以接受
答案 2 :(得分:1)
所以,这就是我最终的目的(shout是一个只在dev模式下运行的定制函数):
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)
答案 3 :(得分:0)
而不是使用你可以做的参数
function log( msg ) {
if (dev_mode) {
var e = new Error(msg);
console.log(e.stack);
}
}
这将显示调用所有函数的顺序(包括行号和文件)。您可以忽略堆栈的前两行(一行将包含错误消息,一行将包含日志函数,因为您在函数中创建了错误对象)。
如果您想要更强大的日志记录 - 请使用A proper wrapper for console.log with correct line number?作为@DoXicK建议
答案 4 :(得分:0)
有几种方法可以快速解决这个问题。
1 - 使用console.error 不太方便,实际错误将被忽视,并且在控制台输出中看到大量红色可能会对您的士气产生负面影响。简而言之 - 不要使用,除非它是一个非常小的脚本或一些测试
2 - 将您的日志方法添加到Object的原型中 获得当前的范围/模块名称/等等。更加灵活和优雅。
Object.prototype.log = function(message){
console.log({
'message': message,
'caller': this,
'stack':arguments.callee.caller.toString()
});
};
使用(任何地方):
this.log("foo");
您可以添加this线程中的技术以获取对象内的确切函数名称,如下所示:
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())将允许您访问调用它的行号 - 甚至不在所有浏览器上。
创建优雅的调试功能是一项工作
尽管我不愿意承认,另一个暗示reg-exps尝试结果的答案似乎是更快地解决你的问题。
答案 5 :(得分: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");
答案 6 :(得分:-1)
似乎你们所有人都在努力挣扎。我有一个简单的单线解决方案:-
//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`)