【问题标题】:How does extends in TypeScript work?TypeScript 中的扩展是如何工作的?
【发布时间】:2015-11-19 01:49:55
【问题描述】:

以下 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__ 的一个实例。

这一切背后的原因是什么?

【问题讨论】:

  • 也许是为了支持未来的分类?

标签: javascript typescript


【解决方案1】:

在 ECMAScript 对类的支持成为本机之前,extends 函数填充了预期的继承行为。

如果您习惯了普通的 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();

【讨论】:

    【解决方案2】:

    生成的javascript代码可以分为两部分:

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

    用于“继承”基类的静态属性。其实在最新版的type script中,这行代码已经被替换成了

    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 答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      相关资源
      最近更新 更多