Javascript TypeScript-如何继承类并重写lambda方法

Javascript TypeScript-如何继承类并重写lambda方法,javascript,inheritance,typescript,lambda,Javascript,Inheritance,Typescript,Lambda,我有一个继承的类,需要父类有一个虚拟方法,该方法在子类中被重写。这个方法是从基构造函数调用的,需要访问实例属性,所以它需要是一个lambda函数,所以“This”就是“This”。问题是,重写lambda方法对我来说不像重写非lambda方法那样有效。这可能吗?如果没有,我想了解原因 另外,当只从构造函数调用方法时,“this”是否始终与“\u this”相同 class Base { protected prop = null; constructor() {

我有一个继承的类,需要父类有一个虚拟方法,该方法在子类中被重写。这个方法是从基构造函数调用的,需要访问实例属性,所以它需要是一个lambda函数,所以“This”就是“This”。问题是,重写lambda方法对我来说不像重写非lambda方法那样有效。这可能吗?如果没有,我想了解原因

另外,当只从构造函数调用方法时,“this”是否始终与“\u this”相同

class Base {
    protected prop = null;
    constructor() {
        this.init();
        this.initLambda();
    }
    init() {
        console.log("Base init");
    }
    initLambda = () => {
        console.log("Base initLambda");
    }
}
class Derived extends Base {
    constructor() {
        super();
    }
    init() {
        console.log("Derived init");
    }
    initLambda = () => {
        //let x = this.prop;
        console.log("Derived initLambda");
    }
}
输出:
派生初始化

Base initLambda

问题在于lambda是一个属性

编译为javascript时,
Base
类变为

var Base = (function () {
    function Base() {
        this.prop = null;
        this.initLambda = function () {
            console.log("Base initLambda");
        };
        this.init();
        this.initLambda();
    }
    Base.prototype.init = function () {
        console.log("Base init");
    };
    return Base;
}());
如您所见,
initLambda
是在
Base
的构造函数中定义的,因此您无法覆盖它

调用
super()
调用
Base
构造函数,该构造函数使用
Base
中的代码定义
this.initLambda
,并运行它。这就是你的结果


查看

好吧,你不能拥有它。
没有,但它被关闭为“设计”

您应该使用常规方法:

class Base {
    protected prop = null;

    constructor() {
        this.init();
        this.initLambda();
    }

    init() {
        console.log("Base init");
    }

    initLambda() {
        console.log("Base initLambda");
    }
}

class Derived extends Base {
    constructor() {
        super();
    }

    init() {
        console.log("Derived init");
    }

    initLambda() {
        console.log("Derived initLambda");
    }
}
然后它就会起作用

对于保留此的正确
,您始终可以将对该方法的调用作为箭头函数传递:

doit() {
    setTimeout(() => this.init(), 1);
}
setTimeout(this.init.bind(this));
或使用以下功能:

doit() {
    setTimeout(() => this.init(), 1);
}
setTimeout(this.init.bind(this));
此外,typescript编译器生成的
\u这个
东西只是对ES5的arrow函数进行了修改,但是如果您将目标更改为ES6,它将不会使用它


编辑: 可以将绑定的方法另存为成员:

class Base {
    ...
    public boundInit: () => void;

    constructor() {
        ...
        this.boundInit = this.initLambda.bind(this);
        setTimeout(this.boundInit, 500);
    }

...
因此,当我执行
new-Derived()
时,我得到的是:

派生初始化
200毫秒后导出的initLambda//


为什么它需要是一个“lambda”?@NitzanTomer-当函数需要访问“\u this”时,我通常使用“实例箭头函数”,以确保我始终拥有正确的上下文。我不相信箭头函数会做你认为的事情。其中的
this
将成为周围环境的
this
。你说*这个方法是从基构造函数调用的,需要访问实例属性,所以它需要是一个lambda函数,所以“This”是“_This”*,但我认为你不理解如何派生类。构造函数中调用的方法将始终调用基类上的版本(如果存在),即使它是以正常方式定义的。我想您可以说您可以重写它,但在实例化之前它不会被重写。@user210757 yes。基本上,不要在基构造函数中调用
this.initLambda()
,在
Derived
中重写它,然后从
Derived
中调用它。按照这些思路,我认为这可能在基构造函数中起作用,但没有-让x=()=>this.initLambda();x();您可以将这样的绑定函数保存为成员,然后使用它们。你认为“不工作”是什么意思?没有调用派生方法-这正是我试图做的。检查我的修订答案“有一个问题是打开的,但它被关闭为“按设计”-链接已断开