前兩天用typescript寫代碼的時候,像擴展一下內置的數據類型:Array,結果發現編譯出的js文件,運行時提示找不到擴展的方法。google以後發現如下說法:
Why doesn't extending built-ins like Error
, Array
, and
Map
work?
In ES2015, constructors which return an object implicitly substitute the value of
this
for any callers of super(...)
.It is necessary for generated constructor code to capture any potential return value of
super(...)
and replace it with this
.
As a result, subclassing Error
, Array
, and others may no longer work as expected.This is due to the fact that constructor functions for
Error
, Array
, and the like use ECMAScript 6's new.target
to adjust the prototype chain;however, there is no way to ensure a value for
new.target
when invoking a constructor in ECMAScript 5.Other downlevel compilers generally have the same limitation by default.
下面給大家 一個實例和詳細的解釋,分享一下心得。
問題起因:
在TypeScript中,extends built-in type, 並且使用ES5庫(target:ES5)進行編譯。
實例:
TS代碼:
編譯後的JS代碼:
// this will return the Array instead of this(NewArray) which means "this" is substituted
大家可以留意一下, built-in的數據類型,在調用apply方法時,會返回自身的數據類型,導致子類(NewArray)的構造函數返回的是Array,而不是NewArray,以至於在實例化NewArray時,它的__proto__是Array的prototype而不是NewArray的prototype,所以導致NewArray的實例,並沒有包涵NewArray prototype裏定義的方法(i.e. getFirst)。
但是在自定義類的擴展沒有問題,大家可以調試看看,因爲自動的類,最終可以保證構造函數返回的this,沒有被降級。
解決方法:
目前沒有找到太好的解決方案,只能等TypeScript下一個版本可以解決這個問題。目前在使用ES5庫的時候,先不要extends built-in的類型了。如果大家找到什麼好的方法,請回復我哦。