问题描述
我有一个类 Parent
和一个扩展 Child
的类 Parent
。
在 Parent
的构造函数中,我现在需要确定 x
是原始类的实例还是子类的实例。
就我而言,Parent
实际上是匿名的,我使用的 instanceof of this.constructor
没有按预期工作:
class Parent {
constructor(x) {
if (x instanceof this.constructor) {
console.log("x is instanceof of this.constructor");
}
if (x instanceof Parent) {
console.log("x is instanceof of Parent");
}
}
}
class Child extends Parent {
constructor(x) {
super(x);
}
foo(x) {
new this.constructor(new super.constructor(x))
}
}
打电话
new Child().foo()
现在产生 x is instanceof of Parent
而不是 x is instanceof of this.constructor
。我做错了什么,如何在不使用 x is instanceof of *Parent*
的情况下解决此问题?
这一切的原因是我包装了我的类定义,以便我可以在没有 new
的情况下创建一个新实例。该类在包装/变异后分配给 Parent
,因此包装的类应该是匿名的。
我不知道这是否有意义,我简化的示例可能无法说明这一切的意义所在,但除了上面解释的一个问题之外,它实际上非常方便:
X() // create new instance of Parent without new
X.f // access static methods
const { X,c: Parent } = function (c) {
return {
X: Object.assign(
function () {
return new c(...arguments);
},_.pick(c,Object.getownPropertyNames(c) // using lodash here
.filter(n => typeof c[n] === "function")
)
),c
};
}(class {
constructor(x) {
if (x instanceof this.constructor) {
console.log("x is instanceof of this.constructor");
}
if (x instanceof Parent) {
console.log("x is instanceof of Parent");
}
}
})
class Child extends Parent {
constructor(x) {
super(x);
}
foo(x) {
new this.constructor(new super.constructor(x))
}
}
解决方法
首先Parent
和Child
标识符的绑定是Parent和Child类的构造函数和常量。当用作 Object.assign
的第一个参数时,Parent
绑定尚未创建但是在将方法分配给函数 c
时,该函数实际上不是叫。因此,稍后在调用类构造函数代码时,Parent
和 Child
变量均引用相应的类构造函数。
因此
class {
constructor(x) {
if (x instanceof Parent) {
console.log("x is instanceof of Parent");
if( x instance of Child) {
console.log("x is instance of Child");
}
}
}
应指明参数是 Parent
或 Child
的实例。当然因为类扩展把Parent.prototype
放在Child.prototype
的继承链的头部,所以Child
的每一个实例也是Parent
的一个实例。
从代码检查 instanceof
值中获得的结果符合预期:
-
foo
创建一个[Object Parent]
对象参数以传递给Child
构造函数 -
Child
使用以下形式提供的参数调用超级构造函数:super([Parent Object])
但是
this
看到的super
值设置为新的Child
对象实例。 -
在超级构造函数中,
[Object Parent] x
参数不是this.constructor
的实例,它是Child
,因此不会生成这样的消息。
您可能希望看看是否可以通过使用较少的复杂性来简化完整的代码,遵循以下结构线:
class Parent {..........}
class Child extends Parent {.....}
const X = Object.assign(.......)