javascript - 属性复制到继承类型的目的

标签 javascript inheritance prototype typescript

在使用在线 TypeScript 编译器时,我注意到创建者选择在以下方法的帮助下实现继承(我已使该方法更具可读性):

var __extends = function(type, base) {
    for (var prop in base) { // why copy the properties?
        if (base.hasOwnProperty(prop)) {
            type[prop] = base[prop];
        }
    }
    function __() { // <- ?
        this.constructor = type;
    }
    __.prototype = base.prototype.
    type.prototype = new __();
};

然后按以下方式使用该方法:

var Item = (function () {
    function Item() {
    }
    return Item;
})();

var Sword = (function (base) {
    __extends (Sword, base);
    function Sword() {
        base.call(this);
    }
    return Sword;
})(Item);

我很难理解 __extends 方法的实现。
从扩展类型手动复制所有属性的目的是什么?继承原型(prototype)不会解决这个问题吗?

与直接复制的属性相比,在原型(prototype)树中搜索属性是否会降低性能?

第二部分的目的我也看不懂。而不是这样做:

function __() {
    this.constructor = type;
}
__.prototype = base.prototype.
type.prototype = new __();

这不能简单地实现为:

type.prototype = base.prototype;

最佳答案

好问题。让我们分解一下。

var __extends = function(type, base) {
    // ** Begin static-side inheritance **
    for (var prop in base) {
        if (base.hasOwnProperty(prop)) {
            type[prop] = base[prop];
        }
    }
    // ** End static-side inheritance **

    // ** Begin Object.create polyfill **
    function __() { // <- ?
        this.constructor = type;
    }
    __.prototype = base.prototype.
    // ** End Object.create polyfill **

    // ** Prototype setup **
    type.prototype = new __();
};

首先是静态端继承。 TypeScript 的类型系统强制要求,如果某些类型具有静态方法,则派生类也具有该方法(或者其签名是基类方法的子类型的方法)。这对于工厂模式之类的东西很有用,例如:

class Car {
    static create(name: string, topSpeed: number): Car {
        // ...
        return new this(/* ... */);
    }
}

class RaceCar extends Car {
    // RaceCar ignores topSpeed because it goes super fast
    static create(name: string): RaceCar {
        // ...
        return new this(/* ... */);
    }   
}

class Truck extends Car {
}

function makeTestCar(t: typeof Car) {
    return t.create('test', 60);
}
var car = makeTestCar(Car); // returns an instance of Car
var raceCar = makeTestCar(RaceCar); // returns an instance of RaceCar
var truck = makeTestCar(Truck); // OK, even though Truck doesn't explicitly implement 'create'

请注意,在最后一行中,Truck 类通过其基类 Car 获得了它的 create 方法。需要复制,因为 Truck.__proto__ 不是 Car

接下来我们有 Object.create polyfill。仅仅编写 type.prototype = base.prototype 是不够的,因为 __proto__ (AKA [[proto]]) 和 prototype 成员不是一回事。 SO 上的其他答案对原型(prototype)继承进行了更好的概述,因此我将遵从这些答案。

最后一行设置构造函数的原型(prototype),使创建的对象具有正确的__proto__

关于javascript - 属性复制到继承类型的目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20038289/

相关文章:

C++ 如何从具有一个参数的派生类构造函数调用具有两个参数的父类(super class)构造函数?

javascript - JS继承原型(prototype)时如何传递参数?

javascript - 从javascript中的原型(prototype)函数访问构造函数名称

javascript - 等待循环中的 promise

javascript - 遍历 DOM 以根据每个 anchor 显示单独的内容

javascript - 如何按照脚本的比例重新计算列之间的值?

python - 类交叉引用?

PHP 继承 : child class overriding parent variable/property for use in constructor

Promise.prototype.then 中的 Javascript 函数不执行

javascript - 未捕获的类型错误 : Property 'fn' of object [object DOMWindow] is not a function