在类字段初始化后,以理智的方式运行"构造函数"或函数?



我想使用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
}

相关内容

最新更新