我使用以下内容获取JavaScript调用者函数名称:
var callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 8, callerFunc.indexOf("(")) || "anoynmous")
有没有办法发现调用该方法的行号?
另外,有没有办法获取调用该方法的JavaScript文件的名称?或源URL?
答案 0 :(得分:89)
这适用于chrome / QtWebView
function getErrorObject(){
try { throw Error('') } catch(err) { return err; }
}
var err = getErrorObject();
var caller_line = err.stack.split("\n")[4];
var index = caller_line.indexOf("at ");
var clean = caller_line.slice(index+2, caller_line.length);
答案 1 :(得分:23)
kangax的解决方案引入了不必要的try..catch范围。如果您需要访问JavaScript中的某些行号(只要您使用的是Firefox或Opera),只需访问(new Error).lineNumber
。
答案 2 :(得分:8)
我很惊讶大多数这些答案都假设你想要处理错误,而不仅仅是为正常情况输出有用的调试跟踪。
例如,我喜欢使用这样的console.log
包装器:
consoleLog = function(msg) {//See https://stackoverflow.com/a/27074218/470749
var e = new Error();
if (!e.stack)
try {
// IE requires the Error to actually be thrown or else the
// Error's 'stack' property is undefined.
throw e;
} catch (e) {
if (!e.stack) {
//return 0; // IE < 10, likely
}
}
var stack = e.stack.toString().split(/\r\n|\n/);
if (msg === '') {
msg = '""';
}
console.log(msg, ' [' + stack[1] + ']');
}
这最终会将以下输出打印到我的控制台:
1462567104174 [getAllPosts@http://me.com/helper.js:362:9]
请参阅https://stackoverflow.com/a/27074218/以及A proper wrapper for console.log with correct line number?
答案 3 :(得分:4)
这通常是通过从当前上下文中抛出错误来实现的;然后分析lineNumber
和fileName
(某些浏览器有)
function getErrorObject(){
try { throw Error('') } catch(err) { return err; }
}
var err = getErrorObject();
err.fileName;
err.lineNumber; // or `err.line` in WebKit
不要忘记callee.caller
属性已被弃用(并且从未真正在ECMA第3版中出现过)。
答案 4 :(得分:3)
看起来我有点迟了:),但讨论非常有趣所以..在这里它...假设您想构建一个错误处理程序,并且您正在使用自己的异常处理程序类,如:
function errorHandler(error){
this.errorMessage = error;
}
errorHandler.prototype. displayErrors = function(){
throw new Error(this.errorMessage);
}
你要像这样包装你的代码:
try{
if(condition){
//whatever...
}else{
throw new errorHandler('Some Error Message');
}
}catch(e){
e.displayErrors();
}
很可能你会在单独的.js文件中使用错误处理程序。
你会注意到在firefox或chrome的错误控制台中显示的代码行号(和文件名)是引发'Error'异常的行(文件)而不是你真正想要的'errorHandler'异常使调试变得容易。抛出自己的异常是很好的,但是在大型项目中找到它们可能是一个很大的问题,特别是如果它们有类似的消息。因此,您可以做的是将对实际空的Error对象的引用传递给您的错误处理程序,并且该引用将保存您想要的所有信息(例如在firefox中,您可以获取文件名,行号等等。 ;在chrome中,如果您读取Error实例的'stack'属性,则会得到类似的东西。 长话短说,你可以这样做:
function errorHandler(error, errorInstance){
this.errorMessage = error;
this. errorInstance = errorInstance;
}
errorHandler.prototype. displayErrors = function(){
//add the empty error trace to your message
this.errorMessage += ' stack trace: '+ this. errorInstance.stack;
throw new Error(this.errorMessage);
}
try{
if(condition){
//whatever...
}else{
throw new errorHandler('Some Error Message', new Error());
}
}catch(e){
e.displayErrors();
}
现在您可以获得引发自定义异常的实际文件和行号。
答案 5 :(得分:3)
行号实际上是静态的,所以如果您只是想要它进行日志记录,那么它可以像gulp一样进行预处理。我写了一个小小的gulp plugin就是这样做的:
var gulp = require('gulp');
var logLine = require('gulp-log-line');
gulp.task('log-line', function() {
return gulp.src("file.js", {buffer : true})
//Write here the loggers you use.
.pipe(logLine(['console.log']))
.pipe(gulp.dest('./build'))
})
gulp.task('default', ['log-line'])
这会将文件名和行附加到console.log中的所有日志,因此console.log(something)
将变为console.log('filePath:fileNumber', something)
。优点是,现在您可以连接文件,转换它们......然后您仍然可以获得该行
答案 6 :(得分:2)
如果您想知道用于调试目的的行号,或仅在开发期间(出于某种原因),您可以使用Firebug(Firefox扩展名)和throw例外。
修改强>:
如果您确实需要在生产中出于某种原因这样做,您可以预处理您的javascript文件,以便每个函数跟踪它所在的行。我知道一些框架可以找到代码的覆盖范围(例如JSCoverage)。
例如,假设你的原始电话是:
function x() {
1 + 1;
2 + 2;
y();
}
你可以写一个预处理器来实现:
function x() {
var me = arguments.callee;
me.line = 1;
1 + 1;
me.line = 2;
2 + 2;
me.line = 3;
y();
}
然后在y()
中,您可以使用arguments.callee.caller.line
来了解调用它的行,例如:
function y() {
alert(arguments.callee.caller.line);
}
答案 7 :(得分:1)
以下是我根据此论坛上的信息撰写的内容:
这是MyDebugNamespace的一部分,Debug显然是保留的,不会作为命名空间名称。
var DEBUG = true;
...
if (true == DEBUG && !test)
{
var sAlert = "Assertion failed! ";
if (null != message)
sAlert += "\n" + message;
if (null != err)
sAlert += "\n" + "File: " + err.fileName + "\n" + "Line: " + err.lineNumber;
alert(sAlert);
}
...
如何致电:
MyDebugNamespace.Assert(new Error(""), (null != someVar), "Something is wrong!")
我在我的命名空间中包含两个带有可变数量参数的函数,这些函数在我的命名空间中调用此基本代码,以便可选地在调用中省略消息或错误。
这适用于Firefox,IE6和Chrome报告fileName和lineNumber为undefined。
答案 8 :(得分:1)
以下代码适用于Mozilla和Chrome。
其日志功能,显示文件的名称和调用者的行。
log: function (arg) {
var toPrint = [];
for (var i = 0; i < arguments.length; ++i) {
toPrint.push(arguments[i]);
}
function getErrorObject(){
try { throw Error('') } catch(err) { return err; }
}
var err = getErrorObject(),
caller;
if ($.browser.mozilla) {
caller = err.stack.split("\n")[2];
} else {
caller = err.stack.split("\n")[4];
}
var index = caller.indexOf('.js');
var str = caller.substr(0, index + 3);
index = str.lastIndexOf('/');
str = str.substr(index + 1, str.length);
var info = "\t\tFile: " + str;
if ($.browser.mozilla) {
str = caller;
} else {
index = caller.lastIndexOf(':');
str = caller.substr(0, index);
}
index = str.lastIndexOf(':');
str = str.substr(index + 1, str.length);
info += " Line: " + str;
toPrint.push(info);
console.log.apply(console, toPrint);
}
答案 9 :(得分:1)
我对JavaScript中自定义错误的贡献:
首先,我同意Inheriting from the Error object - where is the message property?的这个@BT家伙,我们必须正确构建它(实际上你必须使用js对象库,我最喜欢的:https://github.com/jiem/my-class):< / p>
window.g3 = window.g3 || {};
g3.Error = function (message, name, original) {
this.original = original;
this.name = name || 'Error.g3';
this.message = message || 'A g3.Error was thrown!';
(original)? this.stack = this.original.stack: this.stack = null;
this.message += '<br>---STACK---<br>' + this.stack;
};
var ClassEmpty = function() {};
ClassEmpty.prototype = Error.prototype;
g3.Error.prototype = new ClassEmpty();
g3.Error.prototype.constructor = g3.Error;
然后,我们应该定义一个全局错误处理函数(可选),或者它们最终会导致引擎:
window.onerror = printError;
function printError(msg, url, line){
document.getElementById('test').innerHTML = msg+'<br>at: '+url+'<br>line: '+line;
return true;
}
最后,我们应该谨慎地抛出自定义错误:
//hit it!
//throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3');
throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3', new Error());
仅在将第三个参数作为new Error()
传递时,我们能够看到具有函数和行号的堆栈!
在2处,该函数也可以处理引擎引发的错误。
当然,真正的问题是我们真的需要它吗?有些情况(我认为是99%),false
的优雅回报就足够了,只留下一些关键点,以便抛出错误。
答案 10 :(得分:1)
我就是这样做的,我已经在Firefox和Chrome中测试了它。这样就可以检查调用函数的地方的文件名和行号。
logFileAndLineNumber(new Error());
function logFileAndLineNumber(newErr)
{
if(navigator.userAgent.indexOf("Firefox") != -1)
{
var originPath = newErr.stack.split('\n')[0].split("/");
var fileNameAndLineNumber = originPath[originPath.length - 1].split(">")[0];
console.log(fileNameAndLineNumber);
}else if(navigator.userAgent.indexOf("Chrome") != -1)
{
var originFile = newErr.stack.split('\n')[1].split('/');
var fileName = originFile[originFile.length - 1].split(':')[0];
var lineNumber = originFile[originFile.length - 1].split(':')[1];
console.log(fileName+" line "+lineNumber);
}
}
答案 11 :(得分:1)
我意识到这是一个古老的问题,但是现在有一个名为console.trace("Message")
的方法,它将向您显示行号和导致日志的方法调用链以及您传递的消息。 here at freecodecamp和this medium blog post
答案 12 :(得分:1)
所有 JS 代码的全局错误句柄
window.onerror = function (msg, url, lineNo, columnNo, error) {
// ... handle error ...
alert(msg + ' - ' + url + ' - ' + lineNo + ' - ' + columnNo);
return false;
}
适用于所有浏览器:)
对于简单的测试,将此错误代码行添加到您的 js 的任何部分:
aa.ll.kk;//to fire a pure syntax error
答案 13 :(得分:0)
答案很简单。不,不(不)。
当javascript运行时,源文件/网址的概念已经消失了。
也无法确定行号,因为在执行时,代码“行”的概念在Javascript中不再有意义。
特定实现可以提供API挂钩,以允许特权代码访问此类详细信息以进行调试,但这些API不会暴露给普通的标准Javascript代码。
答案 14 :(得分:0)
要确定某个行是什么,您必须搜索占用特定兴趣行的代码的所有代码,并计算从顶部到此感兴趣的“\ n”字符并添加1.
我实际上是在我正在编写的应用程序中执行此操作。它是HTML的最佳实践验证器,并且仍处于开发阶段,但您感兴趣的错误输出过程已经完成。
答案 15 :(得分:0)
console.log(new Error);
它将显示整个曲目。