4

我尝试通过扩展Error构造函数的原型来扩展JavaScript错误属性:

<script type="text/javascript">
// extending the Error properties to all the ones available in the various browsers:
Error.prototype = {
    name: null, // (all browsers); the name of the error
    message: null, // (all browsers); the error message as a string
    description: null, // (Internet Explorer); description of the error
    fileName: null, // (Firefox); the name of the file where the error occurred
    lineNumber: null, // (Firefox); the number of line where the error occurred
    columnNumber: null, // (Firefox); the number of column where the error occurred
    number: null, // (Internet Explorer); the error code as a number
    stack: null // (Firefox, Chrome); detailed information about the location where the error exactly occurred
};

function log(error) {
    var errors = [];

    for (var prop in error) {
        errors.push(prop + ': ' + error[prop]);
    }

    alert(errors.join('\n'));
}
</script>

然后我测试日志功能:

<script type="text/javascript>
try {
    var a = b; // b is undefined!
} catch(error) {
    log(error);
}
</script>

结果是错误对象只显示一些属性(例如在 FirefoxfileNamelineNumbercolumnNumber),就像它没有被扩展一样。

但最奇怪的是,for...in循环似乎无法遍历所有的错误对象属性:试图提醒标准属性error.message通常会返回一条消息。

所以我的测试结果是:

  1. Error 构造函数不能像其他本地构造函数那样通过其原型进行扩展;
  2. for...in循环无法遍历错误对象的属性。

我对吗?
是否有一些有趣的证据/资源,您可以建议了解更多信息?

4

1 回答 1

1

A. 就像 Raynos 说的那样,message没有设置的原因是Error该函数返回一个新的 Error 对象并且不任何方式进行操作this

B. 做到这一点的方法是从构造函数返回 apply 的结果,以及以通常复杂的 javascripty 方式设置原型:

function MyError() {
    var tmp = Error.apply(this, arguments);
    tmp.name = this.name = 'MyError'

    this.stack = tmp.stack
    this.message = tmp.message

    return this
}
    var IntermediateInheritor = function() {}
        IntermediateInheritor.prototype = Error.prototype;
    MyError.prototype = new IntermediateInheritor()

var myError = new MyError("message");
console.log("The message is: '"+myError.message+"'") // The message is: 'message'
console.log(myError instanceof Error)                // true
console.log(myError instanceof MyError)              // true
console.log(myError.toString())                      // MyError: message
console.log(myError.stack)                           // MyError: message \n 
                                                     // <stack trace ...>

在这一点上这样做的唯一问题(我已经迭代了一点)是

  • stack和之外的属性message不包含在MyError和中
  • stacktrace 有一个额外的行,这并不是真正必要的。

第一个问题可以通过使用此答案中的技巧遍历所有不可枚举的错误属性来解决:是否可以获取对象的不可枚举继承属性名称?, 但 ie<9 不支持此功能。第二个问题可以通过撕掉堆栈跟踪中的那一行来解决,但我不确定如何安全地做到这一点(也许只是删除 e.stack.toString() 的第二行??)。

于 2013-08-31T19:39:46.290 回答