0

说我有一个类BaseClass和两个类ClassAClassB它们继承自BaseClassvia

ClassA.prototype = Object.create( BaseClass.prototype );

我想编写一个方法,如果从 的实例调用ClassA,则返回 的新实例,ClassA如果从 的实例调用ClassB,则返回 的新实例ClassB——我想知道最好的方法是什么。目前,在摆弄之后,我想出了以下解决方案,它似乎工作得很好:

// this is added additionally to the above mentioned inheritance setup
ClassA.prototype.constructor = ClassA;
ClassB.prototype.constructor = ClassB;

BaseClass.prototype.newInstance = function () {
    var constructor = this.constructor,
        ClassFactory = constructor.bind.apply( constructor, [constructor].concat( [].slice.call( arguments ) ) );

    return new ClassFactory();
};

明显的缺点就是覆盖了原型的构造函数,感觉不对,因为原型的构造函数其实 BaseClass.

另一种应该起作用的方法是覆盖的方法:

BaseClass.prototype.newInstance = function () {
    throw new Error( 'Cannot call abstract method.' );
};

/** @override */
ClassA.prototype.newInstance = function () {
    var ClassFactory = ClassA.bind.apply( ClassA, [ClassA].concat( [].slice.call( arguments ) ) );

    return new ClassFactory();
};

// ... do the same for ClassB

现在我的问题是询问哪种策略更好,为什么,每种策略的优缺点是什么,即使有更好的方法?

编辑:为了澄清目标是什么,我想最终做这样的事情:

BaseClass.prototype.someMethod = function () {
    var instance = this.getInstance();
    instance.someMethod();

    return instance;
};

现在,由于ClassA并将ClassB继承此方法,我希望它返回调用它的同一类的新实例。

4

1 回答 1

1
ClassA.prototype.constructor = ClassA;
ClassB.prototype.constructor = ClassB;

明显的缺点就是覆盖了原型的构造函数,感觉不对,因为原型的构造函数其实就是BaseClass。

不,原型对象不是由BaseClass. 你只是Object.created 他们,甚至BaseClass.prototype被创建为一个 plain Object

将对象上的属性设置为constructor[back] 构造从该对象继承的实例的函数正是该属性的用途,在这种情况下是正确的。我看不出这个非常简单、实用、高效和预期的解决方案会有什么问题……</p>

特别是如果该getInstance工厂做的事情不仅仅是实例化,并且所有子类都一样,那么“覆盖解决方案”就会失去 DRYness。

但是,也许您根本不需要那种额外的方法,而应该在new this.constructor(args…)任何地方使用。

var ClassFactory = constructor.bind.apply( constructor, [constructor].concat( [].slice.call( arguments ) ) );
return new ClassFactory();

看起来有点复杂,尤其是我不确定这是否适用于所有bind垫片。看看javascript 中的动态对象构造?将 .apply() 与“new”运算符一起使用。这可能吗?.

于 2013-04-20T15:26:11.180 回答