Javascript ES6从现有实例实例化派生类
考虑以下场景:Javascript ES6从现有实例实例化派生类,javascript,ecmascript-6,Javascript,Ecmascript 6,考虑以下场景: class A { constructor() { this.A = 'A'; } createB() { //Create a B instance from this current instance } } class B extends A { constructor() { super(); this.B = 'B'; } } var base = new A(); var derived = new B()
class A {
constructor() {
this.A = 'A';
}
createB() {
//Create a B instance from this current instance
}
}
class B extends A {
constructor() {
super();
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = base.createB();
我希望能够创建B
的实例,而不必创建a
的新实例,而是使用现有的a
实例
我的目标是能够通过调用a
中的函数生成B
实例,但也允许直接创建B
实例,并处理构造默认a
的操作
当
B
扩展A
并需要调用super()
时,我如何实现这样的目标?不确定这正是您想要的,但它适用于您的示例:
class A {
constructor() {
this.A = 'A';
}
}
class B extends A {
constructor() {
super();
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = new B();
Object.assign(fromInstance, base);
console.log(fromInstance);
这里有另一个解决方案。这在C#和Java中非常常见,但由于JS没有方法重载,这有点麻烦,与上述解决方案相比也不太好:
class A {
constructor(source) {
if(source){
//use properties/stuff from source
this.A=source.A;
}
else{
//only perform initialization if source is not provided
this.A = 'A';
}
}
}
class B extends A {
constructor(source) {
super(source);
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = new B(base);
console.log(fromInstance);
基本上,构造函数有两个版本,一个创建全新对象,另一个复制旧对象
我认为这有点误解,不管你做什么,
B
的每一个实例都是定义为a
。如果您希望调用super
,那么您正在调用A
的构造函数,从而“实例化”A
如果我理解这个问题,您希望新实例的A
属性反映创建它的实例的A
属性,对吗?您可以在createB
中设置它,因为它将在A
实例上调用。这将允许B
实例具有隐藏继承的a
A类{
构造函数(){
this.A='A';
}
createB(){
设b=新b()
b、 A=此。A//设置为实例“A”
返回b
}
}
B类扩展了A类{
构造函数(){
超级();
this.B='B';
}
}
var base=newa();
var派生=新的B();
base.A='C';
//从a创建一个B实例,以便
//一个新的a没有被实例化,并且
//fromInstance.A==='C'
var fromInstance=base.createB();
log(fromInstance)
通用方法可以将所有A实例属性复制到新的B实例。一种更通用的方法是先将B对象的属性复制到临时存储中,然后再将它们写回,这样,如果A和B具有相同的属性名称,则B对象的属性将优先:
A类{
构造函数(){
this.A='A';
}
createB(){
设b=新b();
设temp={};
让我们跳一跳,跳一跳;
//保存b的自身属性
Object.keys(b.forEach(bProp=>(temp[bProp]=b[bProp]);
//安装实例自己的属性
Object.keys(this.forEach)(aProp=>(b[aProp]=this[aProp]);
//在实例属性上写回b属性
Object.keys(temp.forEach)(bProp=>(this[bProp]=temp[bProp]);
返回b;
}
}
B类扩展了A类{
构造函数(){
超级();
this.B='B';
}
}
var base=newa();
var派生=新的B();
base.A='C';
//从a创建一个B实例,以便
//一个新的a没有被实例化,并且
//fromInstance.A==='C'
var fromInstance=base.createB();
console.log(“派生的.A=%s”,派生的.A);
log(“fromInstance.A=%s”,fromInstance.A)
只需创建B
的实例,使用对象将A
的当前实例的属性复制到它。分配然后返回它:
createB() {
var b = new B();
Object.assign(b, this);
return b;
}
示例:
A类{
构造函数(){
this.A='A';
}
createB(){
var b=新的b();
对象。分配(b,本);
返回b;
}
}
B类扩展了A类{
构造函数(){
超级();
this.B='B';
}
}
var base=newa();
var派生=新的B();
base.A='C';
var fromInstance=base.createB();
log(来自B的实例instanceof);
log(fromInstance.A)
您确定base.A
属性存在吗?是的,我已经更正了示例中的输入错误this.Name
应该是this.A
我想知道你为什么要这么做,而我现在画的是空白。你想实例化一个没有。。。实例化一个类?您想做什么,您认为您需要代码注释中描述的内容?因为我很确定这不是您真正需要的。@Mike'Pomax'Kamermans我正在将它应用到为MongoDB的NodeJS驱动程序编写的适配器集合中。有一个处理基本操作的DbClient
基类和一个派生的DbCollection
类。理想情况下,我可以直接实例化一个DbCollection类
,并让它自动创建一个DbClient
对象作为基础,以及能够直接从DbClient
实例内部实例化DbCollection
并将其用作基础,而不必创建一个全新的实例,我仍然不明白,如果您有一个类B扩展了a
,那么您可以在B的构造函数中执行任何您喜欢的操作,包括在“成为A”的过程中调用任何可用的内容。即使扩展类隐藏了A的函数,也有super
关键字。你能编辑你的问题,让它真正反映你在做什么,你需要它做什么,而不是使用与类名同名的变量的类吗?这确实解决了手头的主要问题,但是,最好不要为B
的基础构建一个全新的a
实例,因为它将立即被替换。@Haus不管解决方案如何,如果我没有误解的话,您将不得不创建1a
实例和NB
实例。我将编辑答案以包含替代解决方案。