亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

簡單了解TypeScript中如何繼承 Error 類

2024-05-06 16:52:35
字體:
來源:轉載
供稿:網友

前言

在JavaScript 中很多時候都需要自定義錯誤,尤其是開發 Node.js 應用的時候。 比如一個典型的網站服務器可能需要有 NetworkError, DatabaseError, UnauthorizedError 等。 我們希望這些類都擁有 Error 的特性:有錯誤消息、有調用棧、有方便打印的 toString 等。 最直觀的實現方式便是 繼承 Error 類。 但考慮 TypeScript 需要編譯到 ES5 兼容性問題會較為復雜, 本文用來幫助理解 TypeScript 中繼承 Error 的問題來源以及對應的幾種解決方式。

我們需要怎樣的 CustomError

為了容易討論最佳實踐,首先明確我們自定義的 CustomError 需要做到哪些功能。 下面是 Harttle 的觀點:

  1. 可以調用 new CustomError() 來創建,并且 instanceof Error 操作應該返回 true??梢杂脕韯摻ㄊ腔疽?,能夠被視為 Error 的實例能夠兼容既有系統(比如 toString() 要返回調用棧),同時符合慣例。
  2. .stack 屬性首行應為 CustomeError: <message>。如果是 Error: <message> 可能就沒那么漂亮。
  3. .stack 屬性應當包含調用棧并指向 new CustomError() 的那一行。這一點可能是關鍵,如果指向 CustomError 構造函數中的某一行,就會給這個類的使用方造成困惑。

下面舉個例子,這是一個 message 為 "intended" 的 CustomError 的 .stack 屬性值:

CustomError: intendedat Object.<anonymous> (/Users/harttle/Downloads/bar/a.js:10:13)at Module._compile (module.js:653:30)at Object.Module._extensions..js (module.js:664:10)at Module.load (module.js:566:32)at tryModuleLoad (module.js:506:12)at Function.Module._load (module.js:498:3)at Function.Module.runMain (module.js:694:10)at startup (bootstrap_node.js:204:16)at bootstrap_node.js:625:3

ES5 中如何繼承 Error?

Error 是一個特殊的對象,或者說 JavaScript 的 new 是一個奇葩的存在。 為方便后續討論,我們先討論組 ES5 時代是怎樣繼承 Error 的。 我們說 JavaScript 是一門混雜的語言,如何繼承 Error 就是一個典型的例子。 如果你熟悉 原型繼承的方式,應該會寫出如下代碼:

function CustomError (message) {Error.call(this, message)}CustomError.prototype = new Error()

因為 stack 只在 new 的時候生成,上述實現不能滿足功能 2 和功能 3,也就是說:

  • stack 的第一行是總是 Error 而不是 CustomError 且不包含 message 信息。
  • stack 總是指向 new Error() 的那一行,而不是 new CustomError()。

Node 文檔 中描述了一個 captureStackTrace 方法來解決這個問題,改動后的實現如下:

function CustomError (msg) {this.name = 'CustomError'this.message = msgError.captureStackTrace(this, CustomError)}CustomError.prototype = new Error()

其中 .captureStackTrace() 會使用傳入對象的 name 和 message 來生成 stack 的前綴;同時第二個參數用來指定在調用棧中忽略掉哪一部分,這樣棧就會指向 new CustomError 的地方而不是 captureStackTrace() 的地方。

ES6 中如何繼承 Error?

既然 ES6 通過 class 和 extends 等關鍵字給出了類繼承機制, 那么想必通過編寫 CustomError 類來繼承 Error。事實也確實如此,只需要在構造函數中調用父類構造函數并賦值 name 即可實現文章開始提到的三個功能:

class CustomError extends Error {constructor(msg) {super(msg)this.name = 'CustomError'}}

TypeScript 中如何繼承 Error?

ES6 中提供了 new.target 屬性, 使得 Error 的構造函數中可以獲取 CustomError 的信息,以完成原型鏈的調整。 因此 TypeScript 需要編譯到 ES5 時上述功能仍然是無法自動實現。 在 TypeScript 中的體現是形如上述 ES6 的代碼片段會被編譯成:

var CustomError = /** @class */ (function (_super) {__extends(CustomError, _super);function CustomError(msg) {var _this = _super.call(this, msg) || this;_this.name = 'CustomError';return _this;}return CustomError;}(Error));

注意 var _this = _super.call(this, msg) || this; 中 this 被替換掉了。 在 TypeScript 2.1 的 changelog 中描述了這個 Breaking Change。 **這會造成 CustomError 的所有對象方法都無法使用,這里介紹幾種 workaround:

題外話,這個分支可能會導致測試覆蓋率中的 分支未覆蓋問題。可以只在 ES6 下產生測試覆蓋報告來解決。

1. 使用 setPrototypeOf 還原原型鏈

這是 TypeScript 官方給出的解決方法,見這里。

class CustomError extends Error {constructor(message) {super(message);Object.setPrototypeOf(this, FooError.prototype);}}

注意這是一個性能很差的方法,且在 ES6 中提出,兼容性也很差。在不兼容的環境下可以使用 __proto__ 來替代。

2. 堅持使用 ES5 的方式

不使用 ES6 特性,仍然使用本文前面介紹的 『ES5 中如何繼承 Error?』給出的方法。

3. 限制對象方法的使用

雖然 CustomError 的對象函數無法使用,但 CustomError 仍然支持 protected 級別的方法供子類使用,閹割的地方在于自己不能調用。 由于 JavaScript 中對象屬性必須在構造函數內賦值,因此對象屬性也不會受到影響。也就是說:

class CustomError extends Error {count: number = 0constructor(msg) {super(msg)this.count // OK,屬性不受影響this.print() // TypeError: _this.print is not a function,因為 this 被替換了}print() { console.log(this.stack)}}class DerivedError extends CustomError {constructor(msg) {super(msg)super.print() // OK,因為 print 是直接從父類原型獲取的,即 `_super.prototype.print`}}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
www国产亚洲精品久久网站| 亚洲欧美精品一区二区| 久久精品在线视频| 国产一区二区三区免费视频| www国产亚洲精品久久网站| 日韩中文字幕网址| 久久大大胆人体| 欧美专区在线观看| 91精品在线看| 日韩亚洲成人av在线| 中文字幕日韩欧美精品在线观看| 亚洲精品aⅴ中文字幕乱码| 亚洲欧美日本伦理| 亚洲成avwww人| 国产精品成人av性教育| 不卡伊人av在线播放| 日韩av网站在线| 欧美精品在线观看91| 欧美黄色性视频| 亚洲精品久久久久久久久久久| 欧美性猛交xxxx富婆弯腰| 亚洲欧美日本另类| 国产婷婷成人久久av免费高清| 亚洲另类图片色| 色噜噜狠狠色综合网图区| 日韩网站在线观看| 91免费精品视频| 国产精品狼人色视频一区| 久久亚洲精品一区| 精品国偷自产在线| 5252色成人免费视频| 日韩欧美精品在线观看| 国产成人a亚洲精品| 国产黑人绿帽在线第一区| 精品久久久久久中文字幕一区奶水| 欧美大片第1页| 91国产在线精品| 国产欧美精品久久久| 国产精品成人一区二区三区吃奶| 超碰精品一区二区三区乱码| 亚洲视频欧洲视频| 国产精品视频最多的网站| 亚洲欧美在线看| 国产一区av在线| 亚洲美女视频网站| 欧美日韩国产一区二区| 91香蕉亚洲精品| 日韩av一区二区在线| 国产精品视频yy9099| 国产一区二区激情| 俺去了亚洲欧美日韩| 欧美精品video| 成人激情视频小说免费下载| 日韩av电影手机在线| 色偷偷88888欧美精品久久久| 91美女福利视频高清| 欧美午夜激情视频| 91精品久久久久久久久青青| 亚洲综合国产精品| 日韩av在线影视| 精品呦交小u女在线| 亚洲欧美综合另类中字| 欧美在线视频免费播放| 日韩高清免费在线| 91精品视频一区| 欧美午夜片在线免费观看| 日韩高清av在线| 亚洲欧美综合图区| 亚洲天堂av在线免费| 亚洲va久久久噜噜噜久久天堂| 国产精品视频公开费视频| 在线日韩精品视频| 日韩亚洲在线观看| 亚洲人精选亚洲人成在线| 最近2019中文字幕大全第二页| 亚洲人高潮女人毛茸茸| 亚洲欧美国产日韩天堂区| 视频在线观看一区二区| 久久人人爽人人爽爽久久| 全色精品综合影院| 91成人国产在线观看| 国产视频精品一区二区三区| 久久艳片www.17c.com| 久久香蕉国产线看观看网| 亚洲天堂网在线观看| 欧美午夜精品久久久久久久| 欧美俄罗斯性视频| 久久精品最新地址| 日韩精品极品毛片系列视频| 国产精品福利小视频| 亚洲自拍欧美另类| 亚洲第一页中文字幕| 国产精品久久久久av| 亚洲精品欧美极品| 黑人巨大精品欧美一区免费视频| 亚洲va久久久噜噜噜久久天堂| 高潮白浆女日韩av免费看| 韩国精品美女www爽爽爽视频| www.精品av.com| 国产99久久精品一区二区| 中文字幕久久久| 国产成人91久久精品| 精品欧美aⅴ在线网站| 精品在线欧美视频| 在线视频免费一区二区| 国产成人精品在线播放| 国产午夜精品视频免费不卡69堂| 成人网欧美在线视频| 亚洲第一在线视频| 亚洲视频一区二区三区| 欧美激情第99页| 亚洲国产精品久久久久久| 少妇精69xxtheporn| 91经典在线视频| 色综合久久久久久中文网| 欧美色道久久88综合亚洲精品| 亚洲视频在线观看免费| 国产精品亚洲综合天堂夜夜| 欧美性猛交xxxx免费看| 欧美成人精品一区| 91精品在线看| 欧洲成人性视频| 国产精品久久久av久久久| 国产成人鲁鲁免费视频a| 国产中文字幕91| 亚洲精品成人网| 中文字幕日韩精品在线观看| 国产精品18久久久久久麻辣| 91精品国产综合久久香蕉| 国产成人jvid在线播放| 91国内免费在线视频| 久久精品国产欧美亚洲人人爽| 91国产精品视频在线| 中文字幕精品—区二区| 在线色欧美三级视频| 日韩欧美在线国产| 久久精品美女视频网站| 国产精品直播网红| 亚洲美女av电影| 日本久久久久久久久| 色偷偷88888欧美精品久久久| 国产一区二区三区网站| 国产精品99免视看9| 国产精品久久视频| 日韩欧美成人区| 亚洲欧美国产精品久久久久久久| 91视频免费在线| 日韩成人激情视频| 国产精品一区二区久久久久| 91免费福利视频| 国产啪精品视频网站| 午夜精品在线观看| 中文字幕日韩精品在线观看| 亚洲国产精品视频在线观看| 亚洲аv电影天堂网| 欧美成人精品一区二区三区| 最近2019中文字幕mv免费看| 日韩av影片在线观看| 久久6免费高清热精品| 国产亚洲精品美女久久久| 欧美亚洲成人精品| 成人福利视频在线观看| 国产精品爽黄69天堂a| 51ⅴ精品国产91久久久久久|