ES6代碼
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
class Point3D extends Point {
z: number;
constructor(x:number, y:number, z: number) {
super(x,y)
this.z = z;
}
}
編譯
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
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]; };
return extendStatics(d, b);
};
return function (d, b) {//參數d是derive(派生)的簡寫,參數b是base的簡寫
extendStatics(d, b);//繼承靜態成員
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Point = /** @class */ (function () {
function Point(x, y) {
this.x = x;
this.y = y;
}
return Point;
}());
var Point3D = /** @class */ (function (_super) {
__extends(Point3D, _super);
function Point3D(x, y, z) {
// _super.call()用於繼承基類的屬性成員
var _this = _super.call(this, x, y) || this;
_this.z = z;
return _this;
}
return Point3D;
}(Point));
分析
結合《JavaScript高級程序設計》6.3節繼承中所說,在子類構造函數的內部調用基類構造函數,即_super.call(this, x, y)
。這樣在創建子類Point3D
實例的時候就會執行基類構造函數的代碼,獲取基類屬性。
在__extends
函數中主要做了兩件事:
- 將基類的靜態成員賦值到子類。即
extendStatics
函數實現的功能。 - 設置子類函數的原型
針對第二點,簡化代碼如下
function __() { this.constructor = d; }
__.prototype = b.prototype
d.prototype = new __();
如上代碼的最終目的就是d.prototype.__proto__ = b.prototype
。
通過第3行代碼可以看出d.prototype = {__proto__: __.prototype }
結合第2行代碼,可知d.prototype = {__proto__ : b.prototype}
因此可以獲知最終結果d.prototype.__proto__ = b.prototype
。
第一行代碼作用是需要保留原始d.prototype.constructor
。
終極結果就是d.prototype = {__proto__: b.prototype, constructor: d}
。
小結:這裏的function __(){}
作爲中轉函數,將原型鏈傳遞下去。使用結合繼承的方式繼承了普通屬性,靜態屬性和函數。