在子类字段初始化后,以正常的方式运行“构造函数”或函数?

问题描述 投票:0回答:2

我想使用 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 公共字段不会在构造函数之前初始化,仅在 current 构造函数之前初始化。例如,当调用

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 static 字段的,但我没有看到这样的解释如何以编程方式实现这一点mozilla 文档说;在使用
Object.getOwnPropertyDescriptor
检查我上面的立即-.绑定和评估的杂乱之后,我倾向于相信没有办法将属性描述符定义为 thunk;定义可能在从返回后执行
super()
,可能会立即评估并分配给班级,如
let exampleValue = eval(...); Object.defineProperty(..{value:exampleValue})
)。或者我可以做一些可怕的事情,比如在 Superclass.constructor 中做
setTimeout(this.lateConstructor,0)
,但这会破坏很多东西并且不能很好地组合。

我也许可以尝试在任何地方都使用对象的层次结构,但是有没有某种方法可以为父类中的所有子类实现一些全局逻辑?除了用吸气剂让一切变得懒惰之外?感谢您的任何见解。

参考资料:

在构造函数之后运行附加操作——(问题:这需要包装所有子类)

ecmascript-6 constructor field es6-class
2个回答
2
投票

只是想到了一个解决方法(可分层组合)。以一种不太令人满意的方式回答我自己的问题(人们应该随意发布更好的解决方案):

// 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
}

1
投票

我可以创建一个 thunk 在构造函数之后运行吗?

不,这是不可能的。

如何在类字段初始化后以合理的方式运行代码?

将代码放入定义这些字段的类的构造函数中。

有没有办法为父类中的所有子类实现一些全局逻辑?

是:定义一个方法。子类可以从其构造函数中调用它。

© www.soinside.com 2019 - 2024. All rights reserved.