2013-07-08 86 views
6

我正在開發一個小JS庫,並且使用那裏自定義的錯誤異常。擴展JavaScript錯誤/異常

所以,我決定要繼承他們從本地JavaScript Error對象以這種方式(ORLY):

var MyError = function(){ 
    Error.prototype.constructor.apply(this, arguments); 
}; 

// Inherit without instantiating Error 
var Surrogate = function(){}; 
Surrogate.prototype = Error.prototype; 
MyError.prototype = new Surrogate(); 

// Add some original methods 
MyError.prototype.uniqueMethod = function(){...} 

看起來像往常一樣繼承..但是!

var err = new MyError("hello! this is text!"); 
console.log(err.message); // is giving me empty string! 

我看了一下這個hereMDN文章,但他們說我使用的是這樣的:

var MyError = function(msg){ 
    this.message = msg; 
}; 

但我的問題是 - 如果不是在錯誤的構造函數,那麼在哪裏消息被初始化? 可能有人知道錯誤本機構造函數的工作原理?

謝謝!

P.S.如果它很有趣 - 我正在開發Enum.js庫。

+1

使其儘可能簡單: 'var obj = new Error(); Error.call(obj,「Hello,world!」);' 這也行不通。 '錯誤'很奇怪。 – Ryan

+1

@minitech:*「'錯誤'很奇怪。」* +1 –

回答

5

你在做什麼很好。這是Error這就是問題所在。

在此行中:

Error.prototype.constructor.apply(this, arguments); 

...你打電話Error(間接)作爲一個正常的函數調用,而不是作爲一個new表達的一部分,而defined behavior for Error when you call it as a non-constructor function是創建一個新的空白Error並返回它(而不是填充this)。

現在,在正常情況下,您對原型進行的操作將使標準檢查是否將其作爲構造函數(if (this instanceof Error))調用。不幸的是,它似乎並沒有這樣做,無論它使用什麼檢查來確定它是如何調用的,似乎都不會立即適用於你想要做的事情。即使這(這只是一個測試,並不意味着你實際要做的事情):

MyError.prototype = Error.prototype; // You wouldn't normally do this, it's just a test 

......沒有解決它。

This answer to another Stack Overflow question指向一個可能的解決方法(基本上,讓Error創建對象,然後再返回,從MyError):

function MyError(message) { 
    var e = new Error(message); 
    // ...apply your enhancements to `e` 
    return e; 
} 

不驚人的滿意,你不得不直接把您的擴展的對象,而比使用原型鏈,但如果Error拒絕玩球,您的選擇是有限的...

+0

感謝您的回答。所以,似乎我需要做的像這樣:'MyError = function(msg){var err = new Error(); this.msg = msg; this.stack = err.stack; ...} – gobwas

+0

@gobwas:我剛更新了一個可能的解決方法。我不喜歡它,但我不確定你有很多選擇。 *編輯*或者,是的,你可以這樣做。 –

+1

非常感謝,是的,沒有多少選擇=)) – gobwas