[英]checking for typeof error in JS
在 JS 中,似乎無法檢查傳遞給 function 的參數實際上是“錯誤”類型還是錯誤實例。
例如,這是無效的:
typeof err === 'error'
因為只有 6 種可能的類型(以字符串的形式):
typeof 運算符將類型信息作為字符串返回。 typeof
返回六個可能的值:
“數字”、“字符串”、“布爾”、“對象”、“函數”和“未定義”。
但是,如果我有一個像這樣的簡單用例怎么辦:
function errorHandler(err) {
if (typeof err === 'error') {
throw err;
}
else {
console.error('Unexpectedly, no error was passed to error handler. But here is the message:',err);
}
}
那么確定參數是否是錯誤實例的最佳方法是什么?
instanceof
運算符有什么幫助嗎?
您可以使用instanceof
運算符(但請參閱下面的警告!)。
var myError = new Error('foo');
myError instanceof Error // true
var myString = "Whatever";
myString instanceof Error // false
如果錯誤是在與檢查發生位置不同的窗口/框架/iframe 中引發的,則上述方法將不起作用。 在這種情況下, instanceof Error
檢查將返回 false,即使對於Error
對象也是如此。 在這種情況下,最簡單的方法是鴨子類型。
if (myError && myError.stack && myError.message) {
// it's an error, probably
}
但是,如果您有包含stack
和message
屬性的非錯誤對象,則鴨子類型可能會產生誤報。
我問了最初的問題——@Trott 的回答肯定是最好的。
然而,由於 JS 是一種動態語言,並且有如此多的 JS 運行時環境, instanceof
運算符可能會失敗,尤其是在前端開發中跨越 iframe 等邊界時。 參見: https : //github.com/mrdoob/three.js/issues/5886
如果你對鴨子打字沒問題,這應該很好:
let isError = function(e){
return e && e.stack && e.message;
}
我個人更喜歡靜態類型語言,但如果您使用的是動態語言,最好就其本身而言采用動態語言,而不是強迫它表現得像靜態類型語言。
如果你想更精確一點,你可以這樣做:
let isError = function(e){
return e && e.stack && e.message && typeof e.stack === 'string'
&& typeof e.message === 'string';
}
var myError = new Error('foo');
myError instanceof Error // true
var myString = "Whatever";
myString instanceof Error // false
唯一的問題是
myError instanceof Object // true
另一種方法是使用構造函數屬性。
myError.constructor === Object // false
myError.constructor === String // false
myError.constructor === Boolean // false
myError.constructor === Symbol // false
myError.constructor === Function // false
myError.constructor === Error // true
雖然需要注意的是,這個匹配是非常具體的,例如:
myError.constructor === TypeError // false
您可以使用Object.prototype.toString
輕松檢查對象是否為Error
,這也適用於不同的幀。
function isError(obj){
return Object.prototype.toString.call(obj) === "[object Error]";
}
function isError(obj){ return Object.prototype.toString.call(obj) === "[object Error]"; } console.log("Error:", isError(new Error)); console.log("RangeError:", isError(new RangeError)); console.log("SyntaxError:", isError(new SyntaxError)); console.log("Object:", isError({})); console.log("Array:", isError([]));
此行為由 ECMAScript 語言規范保證。
當調用 toString 方法時,采取以下步驟:
- 如果 this 值未定義,則返回“[object Undefined]”。
- 如果 this 值為空,則返回“[object Null]”。
- 讓 O 成為調用 ToObject 並將 this 值作為參數傳遞的結果。
- 令 class 為 O 的 [[Class]] 內部屬性的值。
- 返回字符串值,該值是連接三個字符串“[object”、class 和“]”的結果。
Error 實例從 Error 原型對象繼承屬性,它們的
[[Class]]
內部屬性值為“Error”。 錯誤實例沒有特殊屬性。
你可以定義一個用戶定義的類型守衛,只需要定義一個返回類型為類型謂詞的 function
您可以檢查變量是否是這樣的錯誤
const isError = (err: unknown): err is Error => err instanceof Error;
然后在里面嘗試捕獲驗證這樣的
try {
login(username, password);
} catch (err) {
if (isError(err)) {
console.log(err.message);
}
您可以使用 obj.constructor.name 檢查對象的“類” https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Function_names_in_classes
例如
var error = new Error("ValidationError");
console.log(error.constructor.name);
上面的行將記錄“錯誤”,它是對象的類名。 如果該類不使用名稱為“name”的屬性,則這可以與 javascript 中的任何類一起使用
感謝@Trott 提供您的代碼,我只是使用了相同的代碼並添加了一個實時工作示例以供他人使用。
<html> <body > <p>The **instanceof** operator returns true if the specified object is an instance of the specified object.</p> <script> var myError = new Error("TypeError: Cannot set property 'innerHTML' of null"); // error type when element is not defined myError instanceof Error // true function test(){ var v1 = document.getElementById("myid").innerHTML ="zunu"; // to change with this try { var v1 = document.getElementById("myidd").innerHTML ="zunu"; // exception caught } catch (e) { if (e instanceof Error) { console.error(e.name + ': ' + e.message) // error will be displayed at browser console } } finally{ var v1 = document.getElementById("myid").innerHTML ="Text Changed to Zunu"; // finally innerHTML changed to this. } } </script> <p id="myid">This text will change</p> <input type="button" onclick="test();"> </body> </html>
對於那些正在尋找某種“官方”方式(就像我一樣)的人,這就是MDN 推薦的:
try {
myRoutine();
} catch (e) {
if (e instanceof RangeError) {
// statements to handle this very common expected error
} else {
throw e; // re-throw the error unchanged
}
}
或者將其用於不同類型的錯誤
function isError(val) {
return (!!val && typeof val === 'object')
&& ((Object.prototype.toString.call(val) === '[object Error]')
|| (typeof val.message === 'string' && typeof val.name === 'string'))
}
只需使用error.name
function _err(type = false) { if(type) { throw new TypeError('Oh crap!') } throw new Error('Oh crap!') } try { _err(true) } catch (error) { console.log(typeof error.name, error.name, error.name === 'TypeError') } try { _err() } catch (error) { console.log(typeof error.name, error.name, error.name === 'Error') }
您可以進一步從@iota 獲取答案,並通過getPrototypeOf()
或已棄用的__proto__
屬性檢查測試對象的內部[[Prototype]]
屬性。
如果對象是一個錯誤,它繼承自Error.prototype
。 所以也許是這樣的:
// the object you want to check
const objectToCheck = new Error();
// current way
console.log(Object.getPrototypeOf(objectToCheck) === Error.prototype); /* true*/
// deprecated way
console.log(objectToCheck.__proto__ === Error.prototype); /* true */
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.