我想使用ES6公共类字段:
class Superclass {
constructor() {
// would like to write modular code that applies to all
// subclasses here, or similarly somewhere in Superclass
this.example++; // does NOT WORK (not intialized)
//e.g. doStuffWith(this.fieldTemplates)
}
}
class Subclass extends Superclass {
example = 0
static fieldTemplates = [
Foo,
function() {this.example++},
etc
]
}
问题:
ES6公共字段不会在构造函数之前初始化,只在当前构造函数之前初始化。例如,当调用super()
时,任何子字段都还没有定义,就像this.example
还不存在一样。静态字段将已定义。因此,例如,如果从超类构造函数调用代码function(){this.example++}
和.bind
(视情况而定(,它将失败。
解决方法:
一种解决方法是在所有ES6公共类都已正确初始化之后,放置所有初始化逻辑。例如:
class Subclass extends Superclass {
example = 0
lateConstructor = (function(){
this.example++; // works fine
}).bind(this)()
}
解决方案是什么
然而,这将涉及重写每一个类。我想要这样的东西,只需在Superclass.constructor中定义它,像Object.defineProperty(this, 'lateConstructor', {some magic})
这样神奇的东西(据称,Object.defineProperty
是es6静态字段的内部定义方式,但我在mozilla文档中看不到如何通过程序实现这一点的解释;在使用Object.getOwnPropertyDescriptor
检查我的上述内容后,我倾向于认为没有办法将属性描述符定义为thunk;该定义可能是在从super()
返回后执行的,其可能被立即评估并分配给类(如let exampleValue = eval(...); Object.defineProperty(..{value:exampleValue})
(。或者,我可以做一些可怕的事情,比如在Superclass.constructor中做setTimeout(this.lateConstructor,0)
,但这会破坏很多东西,也不会很好地组合。
我也许可以试着在任何地方都使用对象的层次结构,但有没有办法为父类中的所有子类实现一些全局逻辑?除了用胡瓜让一切变得懒惰之外?感谢您的真知灼见。
参考文献:
在构造函数之后运行附加操作--(问题:这需要包装所有子类(
我可以创建一个在构造函数之后运行的thunk吗?
不,这是不可能的。
如何在类字段初始化后以合理的方式运行代码?
将代码放入定义这些字段的类的构造函数中。
有没有办法为父类中的所有子类实现一些全局逻辑?
是:定义一个方法。子类可以从其构造函数中调用它。
刚刚想到了一个变通方法(可分层组合(。为了回答我自己的问题,以一种有点不令人满意的方式(人们应该可以随意发布更好的解决方案(:
// The following illustrates a way to ensure all public class fields have been defined and initialized
// prior to running 'constructor' code. This is achieved by never calling new directly, but instead just
// running Someclass.make(...). All constructor code is instead written in an init(...) function.
class Superclass {
init(opts) { // 'constructor'
this.toRun(); // custom constructor logic example
}
static make() { // the magic that makes everything work
var R = new this();
R.init(...arguments);
return R;
}
}
class Subclass extends Superclass {
subclassValue = 0 // custom public class field example
init(toAdd, opts) { // 'constructor'
// custom constructor logic example
this.subclassValue += toAdd; // may use THIS before super.init
super.init(opts);
// may do stuff afterwards
}
toRun() { // custom public class method example
console.log('.subclassValue = ', this.subclassValue);
}
}
演示:
> var obj = Subclass.make(1, {});
.subclassValue = 1
> console.log(obj);
Subclass {
subclassValue: 1
__proto__: Superclass
}