说我有一个班级BaseClass
和两个班级ClassA
和ClassB
从BaseClass
通过
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
将继承此方法,我希望它返回与其调用的同一个类的新实例。
答案 0 :(得分:1)
ClassA.prototype.constructor = ClassA; ClassB.prototype.constructor = ClassB;
明显的缺点是覆盖原型的构造函数,这感觉不对,因为原型的构造函数实际上是BaseClass。
不,原型对象不是由BaseClass
构建的。您只需Object.create
d他们,甚至BaseClass.prototype
创建为普通Object
。
将对象[back]上的constructor
属性设置为构造从该对象继承的实例的函数,这正是该属性的用途,在这种情况下是正确的。我不认为这个非常简单,实用,有效和预期的解决方案会出现什么问题......
特别是如果getInstance
工厂做的不仅仅是实例化,而且对于所有子类都是相同的,那么“覆盖解决方案”会丢失DRY。
但是,您可能根本不需要额外的方法,只需在任何地方使用new this.constructor(args…)
。
var ClassFactory = constructor.bind.apply( constructor, [constructor].concat( [].slice.call( arguments ) ) ); return new ClassFactory();
看起来有点复杂,尤其是我不确定这是否适用于所有bind
填充程序。请查看dynamic object construction in javascript?或Use of .apply() with 'new' operator. Is this possible?。