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

时间:2013-11-18 00:54:26

标签: 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方法的实施 从扩展类型手动复制所有属性的目的是什么?不会继承原型来处理那个吗?

在原型树中搜索属性而不是直接复制属性时是否存在性能损失?

第二部分我也无法理解其目的。而不是这样做:

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

这不能简单地实现为:

type.prototype = base.prototype;

2 个答案:

答案 0 :(得分:3)

扩展副本原型和静态成员(浅层副本)。静态是Parent.things和原型是Parent.prototype.things prototype.things的复制方式是Object create的poly填充如何工作。

var __extends = this.__extends || function (d, b) {
    //Copies Item.things to Sword.things
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    //Copies Item.prototype.things to Sword.prototype.things
    //this is a polyfill for Object.create
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var Sword = (function (_super) {
    __extends(Sword, _super);
    function Sword() {
        _super.apply(this, arguments);
    }
    return Sword;
})(Iten);

考虑以下打字稿:

class Item {
    public static DAMAGE = 0;
};

在JavaScript中,这将是:

var Item = (function () {
    function Item() {
    }
    Item.DAMAGE = 0;
    return Item;
})();

我如何使用静态损伤?请参阅以下示例(simplefied JS);

//Using static to make general getters and setters
var Item = function(damage){ 
  this._data = [];
  this.set(Item.DAMAGE,damage)
};
Item.DAMAGE=0;
Item.prototype.get=function(dataIndex){
  return this._data[dataIndex];
};
Item.prototype.set=function(dataIndex,val){
  //maybe execute Item.rules[dataIndex].set(val) for validating value
  this._data[dataIndex] = val;
  return val;
};
var i = new Item(22);
//I could get damage using i.get(0)
//but the following reads more easily
i.get(Itesm.DAMAGE);

关于构造函数,原型,继承,混合和这个值的介绍:https://stackoverflow.com/a/16063711/1641941

答案 1 :(得分:3)

好问题。让我们打破这个。

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类通过其基类create获得了Car方法。需要进行复制,因为Truck.__proto__ 不是 Car

接下来我们有Object.create polyfill。写type.prototype = base.prototype是不够的,因为__proto__(AKA [[proto]])和prototype成员不是一回事。关于SO的其他答案给出了原型继承的更好的概述,所以我会推迟那些。

最后,最后一行设置构造函数的原型,以便创建的对象具有正确的__proto__