2015-08-25 48 views
4

以下打字稿代碼:在TypeScript中如何進行擴展?

class BaseClassWithConstructor { 
    private _id: number; 
    constructor(id: number) { 
     this._id = id; 
    } 
} 

class DerivedClassWithConstructor extends BaseClassWithConstructor { 
    private _name: string; 
    constructor(id: number, name: string) { 
     this._name = name; 
     super(id); 
    } 
} 

生成以下JavaScript代碼:

var __extends = (this && this.__extends) || function (d, b) { 
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 
    function __() { this.constructor = d; } 
    __.prototype = b.prototype; 
    d.prototype = new __(); 
}; 
var BaseClassWithConstructor = (function() { 
    function BaseClassWithConstructor(id) { 
     this._id = id; 
    } 
    return BaseClassWithConstructor; 
})(); 
var DerivedClassWithConstructor = (function (_super) { 
    __extends(DerivedClassWithConstructor, _super); 
    function DerivedClassWithConstructor(id, name) { 
     this._name = name; 
     _super.call(this, id); 
    } 
    return DerivedClassWithConstructor; 
})(BaseClassWithConstructor); 

extends似乎是由__extends功能來實現。

正試圖解決這個功能背後的魔法。我不明白爲什麼 我們必須將基類中的屬性複製到派生類(即for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];),並使用__函數創建一個新對象,並將b,__,d__

這是什麼原因?

+0

也許支持未來的分類? –

回答

0

直到ECMAScript對類的支持都是原生的,擴展函數纔會填充預期的繼承行爲。

如果你習慣於正常的JavaScript原型繼承,你會想知道爲什麼它不只是做__.prototype = b.prototype;部分。如果是這樣,你會有興趣知道增加for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];意味着靜態成員也會被複制。例如...

class BaseClassWithConstructor { 
    private _id: number; 
    constructor(id: number) { 
     this._id = id; 
    } 

    static doIt() { 
     alert('Done it'); 
    } 
} 

class DerivedClassWithConstructor extends BaseClassWithConstructor { 
    private _name: string; 
    constructor(id: number, name: string) { 
     this._name = name; 
     super(id); 
    } 
} 

DerivedClassWithConstructor.doIt(); 
0

生成的JavaScript代碼可以在兩個部分可分爲:

for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];

爲「繼承」基類的靜態屬性。實際上,在類型的腳本的最新版本,這行代碼已經被替換爲

extendStatics(d, b);

其中extendStatics的定義是:

var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };

唯一的區別是,在新版本,如果瀏覽器支持相關行爲,則使用[[prototype]]的操作,否則回退到舊練習,即將每個擁有的屬性從基類複製到派生類。


至於

function __() { this.constructor = d; } __.prototype = b.prototype; d.prototype = new __();

這是真的dprototype設置的b一個新實例的稍微華麗的方式。但不是直接將new b(...)分配到d.instance,而是使用虛擬構造函數__,因爲爲了設置原型,我們不需要真正調用構造函數b,並且通過使用虛函數,我們不需要傳遞參數到構造函數。見this SO回答。