在构造函数中定义方法或作为常规类方法之间的typescript有什么区别?

时间:2016-10-19 14:04:01

标签: angularjs typescript

我正在将一个角度1的应用程序从javascript迁移到typescript。实际上一切都已完成,但我无法理解一个具体案例。

我有一些使用链接功能的指令。

伪代码中的

class SomeDirective implements ng.IDirective{
    static $inject=['someService'];
    public restrict: string='EA';
    public scope: any;
    constructor(private someService: SomeService){
        this.scope={
            data: '='
        }
    }
}

现在我想定义一个像

这样的链接函数
public link(scope, ele, attrs){
     do some action with this.someService.someField
}

如果我在类中定义了这个方法,那么我会收到一个错误:未找到属性'someField'。

如果我在构造函数中按如下方式定义方法,那么它确实有效。有什么区别?

this.link=(scope,ele,attrs)=>{
    do some action with this.someService.someField
}

link在此定义为any类型的类属性。

1 个答案:

答案 0 :(得分:1)

在构造函数中定义函数会在您编写时创建一个类属性,并且仅将其分配给实例。
另一方面,类方法在原型上定义:

class A {
    fn2: () => void;

    constructor() {
        this.fn2 = () => {
            console.log("A.fn2");
        };
    }

    fn1(): void {
        console.log("A.fn1");
    }
}

编译成:

var A = (function () {
    function A() {
        this.fn2 = function () {
            console.log("A.fn2");
        };
    }
    A.prototype.fn1 = function () {
        console.log("A.fn1");
    };
    return A;
}());

如果要覆盖派生类中的函数,则使用实例函数会出现问题:

class B extends A {
    constructor() {
        super();

        this.fn2 = () => {
            super.fn2(); // Error: Only public and protected methods of the base class are accessible via the 'super' keyword
            console.log("B.fn2");
        };
    }

    fn1(): void {
        super.fn1();
        console.log("A.fn1");
    }
}

code in playground

您可以在分配新功能(this.fn2)之前保存之前B的参考,以便您有超级电话,但这不是非常舒服。

当然加上(如果您使用箭头功能),这些功能是开箱即用的this权限。

由您来决定对您更重要的是什么,我更喜欢方法,如果我将它们作为回调传递,那么我只是bind them

修改

当您定期调用方法时,右this应始终正确:

class A {
    bound: () => void;

    constructor() {
        this.bound = () => {
            console.log("bound: ", this);
        };
    }

    unbound(): void {
        console.log("unbound: ", this);
    }
}

let a1 = new A();
a1.bound(); // A {}
a1.unbound(); // A {}

正如预期的那样,this这里是A的实例,但是:

function later(fn: Function) {
    setTimeout(fn, 100);
}

later(a1.bound); // A {}
later(a1.unbound); // Window { ... }

code in playground

正如您在此处所见,使用a1.unbound调用setTimeout时(或者如果您将其作为回调传递),则this不是{{1}的实例}}。
这可以修复如下:

A