談談在Tyepscript(version:2.2.2)擴展(extends)built-in類型(e.g. Array)的問題

前兩天用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代碼:

class NewArray<T> extends Array<T>{
getFirst() {
return 'NewArray';
}
}
var newAry = new NewArray<string>();
console.log(newAry.getFirst()); // here will error out of undefined method

編譯後的JS代碼:

var NewArray = (function (_super) {
__extends(NewArray, _super);
function NewArray() {
// this will return the Array instead of this(NewArray) which means "this" is substituted
return _super !== null && _super.apply(this, arguments) || this;
}
NewArray.prototype.getFirst = function () {
return 'NewArray';
};
return NewArray;
}(Array));

大家可以留意一下, built-in的數據類型,在調用apply方法時,會返回自身的數據類型,導致子類(NewArray)的構造函數返回的是Array,而不是NewArray,以至於在實例化NewArray時,它的__proto__是Array的prototype而不是NewArray的prototype,所以導致NewArray的實例,並沒有包涵NewArray prototype裏定義的方法(i.e. getFirst)。

但是在自定義類的擴展沒有問題,大家可以調試看看,因爲自動的類,最終可以保證構造函數返回的this,沒有被降級。


解決方法:

目前沒有找到太好的解決方案,只能等TypeScript下一個版本可以解決這個問題。目前在使用ES5庫的時候,先不要extends built-in的類型了。如果大家找到什麼好的方法,請回復我哦。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章