4

我試圖通過原型Error構造的延伸擴展JavaScript錯誤性質:擴展本地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> 

的結果是錯誤對象只顯示一些屬性(例如,在Firefox fileNamelineNumbercolumnNumber),如果它沒有被擴展。

但最奇怪的是,for...in週期似乎無法行走的所有錯誤對象屬性:試圖提醒標準屬性error.message正常返回的消息。

所以我測試的結果是:

  1. Error構造不是通過其原型可擴展的,其他原生構造函數;
  2. for...in循環無法行走錯誤對象的屬性。

對嗎?
是否有一些有趣的證據/資源可能會建議您更多地瞭解它?

+1

'Error'是一個宿主對象,因此不必像JavaScript的「普通」對象那樣工作。 –

+0

嗯,有趣,我不知道主機對象。我通過Stackoverflow線程學習了一些東西。至於現在,我知道它們是具有特殊屬性和行爲的特殊對象,比如DOM對象,我說得對嗎? –

+3

請參閱http://es5.github.com/#x4.3.8。如果您在本網站上搜索「主機對象」,您會發現一些關於它們的有趣聲明。*編輯*:它們基本上是對象提供的環境而不是規範的一部分(就像DOM對象一樣,是的)。但問題可能只是'Error.prototype'不可寫(至少在Firefox中)。 'var obj = {foo:'bar'}; Error.prototype = obj; Error.prototype == obj;'產生'false'。 –

回答

0

A.像,Raynos說,究其原因message沒有被設置的是Error是返回一個新的Error對象和不不以任何方式操縱一個this功能。

B.要做到這一點正確的方法是返回從構造函數的應用,結果以及設置在一般的複雜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 ...> 

唯一的問題這樣在這一點上做的(我iteratted這一點)是

stackmessage其他
  • 性能不包含在MyError
  • 的stacktrace有一個額外的行,這是不是真的有必要。

第一個問題可以通過使用這個答案的伎倆,通過錯誤的所有非枚舉的屬性迭代是固定的:Is it possible to get the non-enumerable inherited property names of an object?,但這不是由即< 9.第二個問題可以支持所要解決撕掉堆棧跟蹤中的那一行,但我不知道如何安全地做到這一點(也許只是刪除第二行e.stack.toString()??)。