Typescript:无法访问继承类构造函数中的成员值 [英] Typescript: can not access member value in inherited class constructor

查看:145
本文介绍了Typescript:无法访问继承类构造函数中的成员值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 A 的类,以及从它继承的类 B

I have a class A, and a class B inherited from it.

class A {
    constructor(){
        this.init();
    }
    init(){}
}

class B extends A {
    private myMember = {value:1};
    constructor(){
        super();
    }
    init(){
        console.log(this.myMember.value);
    }
}

const x = new B();

当我运行此代码时,出现以下错误:

When I run this code, I get the following error:

Uncaught TypeError: Cannot read property 'value' of undefined

如何避免此错误?

我很清楚JavaScript代码将调用 init 在创建 myMember 之前的方法,但应该有一些练习/模式使其有效。

It's clear for me that the JavaScript code will call the init method before it creates the myMember, but there should be some practice/pattern to make it work.

推荐答案

这就是为什么在某些语言(咳嗽C#)中,代码分析工具会在构造函数中标记虚拟成员的使用。

This is why in some languages (cough C#) code analysis tools flag usage of virtual members inside constructors.

在Typescript字段初始化中在调用基础构造函数之后,在构造函数中发生。字段初始化写在字段附近的事实只是语法糖。如果我们查看生成的代码,问题就会变得清晰:

In Typescript field initializations happen in the constructor, after the call to the base constructor. The fact that field initializations are written near the field is just syntactic sugar. If we look at the generated code the problem becomes clear:

function B() {
    var _this = _super.call(this) || this; // base call here, field has not been set, init will be called
    _this.myMember = { value: 1 }; // field init here
    return _this;
}

您应该考虑从实例外部调用init的解决方案,并且不在构造函数中:

You should consider a solution where init is either called from outside the instance, and not in the constructor:

class A {
    constructor(){
    }
    init(){}
}

class B extends A {
    private myMember = {value:1};
    constructor(){
        super();
    }
    init(){
        console.log(this.myMember.value);
    }
}

const x = new B();
x.init();   

或者你可以为你的构造函数添加一个额外的参数来指定是否调用 init 并且也不在派生类中调用它。

Or you can have an extra parameter to your constructor that specifies whether to call init and not call it in the derived class as well.

class A {
    constructor()
    constructor(doInit: boolean)
    constructor(doInit?: boolean){
        if(doInit || true)this.init();
    }
    init(){}
}

class B extends A {
    private myMember = {value:1};
    constructor()
    constructor(doInit: boolean)
    constructor(doInit?: boolean){
        super(false);
        if(doInit || true)this.init();
    }
    init(){
        console.log(this.myMember.value);
    }
}

const x = new B();

或者非常非常脏的解决方案setTimeout ,将推迟初始化直到当前帧完成。这将让父构造函数调用完成,但是当构造函数调用和超时到期时,对象还没有 init ed

Or the very very very dirty solution of setTimeout, which will defer initialization until the current frame completes. This will let the parent constructor call to complete, but there will be an interim between constructor call and when the timeout expires when the object has not been inited

class A {
    constructor(){
        setTimeout(()=> this.init(), 1);
    }
    init(){}
}

class B extends A {
    private myMember = {value:1};
    constructor(){
        super();
    }
    init(){
        console.log(this.myMember.value);
    }
}

const x = new B();
// x is not yet inited ! but will be soon 

这篇关于Typescript:无法访问继承类构造函数中的成员值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆