从ES6代码编译看原型链继承

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 __(){}作为中转函数,将原型链传递下去。使用结合继承的方式继承了普通属性,静态属性和函数。

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