简体   繁体   English

打字机回调函数中的'this'范围

[英]'this' scope in typescript callback function

I cannot understand how 'this' context works in typescript. 我无法理解'this'语境如何在打字稿中起作用。 I cannot access class members in methods. 我无法访问方法中的类成员。 Below is my code 以下是我的代码

class adopterDetailCtrl {
    public adopter: IAdopter;
    public $router: any;

    static $inject = ['app.common.services.AdopterService'];
    constructor(private adopterService: app.common.services.IAdopterServices) {
        this.adopter = null;
    }

    $routerOnActivate(next) {
        if (next.params.id > 0) {
            this.getAdopterById(next.params.id);
        }
    }

    getAdopterById(adopterId: number): void {
        var AdopterList = this.adopterService.getAdopterById();
        AdopterList.query({ id: adopterId }, (data: adopter.IAdopter[]) => {
            this.adopter = data[0];//this.adopter is undefined here. this refers to 'window'
        });
    }

    setAdopter(data: IAdopter) {
        this.adopter = data;//can access this.adopter
    }
}

The this context is just the same in typescript as it as in javascript, as the code you actually run is the compiled javascript that the typescript compiler outputs. this上下文在打字稿中与在javascript中一样,因为你实际运行的代码是typescript编译器输出的已编译的javascript。

In javascript you have two ways to deal with this issue: 在javascript中,您有两种方法可以解决此问题:

  1. Use the arrow function 使用箭头功能
  2. Use the Function.prototype.bind function 使用Function.prototype.bind函数

You are probably passing getAdopterById as a callback, if that's the case then it will be easy to solve using bind : 您可能正在将getAdopterById作为回调传递,如果是这种情况,那么使用bind将很容易解决:

let myobj = new adopterDetailCtrl(...);

...

someFunction(myobj.getAdopterById.bind(myobj));

You can also modify the reference for the method of the instance in the ctor: 您还可以在ctor中修改实例方法的引用:

(1) (1)

class adopterDetailCtrl {
    public adopter: IAdopter;
    public $router: any;

    static $inject = ['app.common.services.AdopterService'];
    constructor(private adopterService: app.common.services.IAdopterServices) {
        this.adopter = null;

        this.getAdopterById = (adopterId: number) => {
            var AdopterList = this.adopterService.getAdopterById();
            AdopterList.query({ id: adopterId }, (data: adopter.IAdopter[]) => {
                this.adopter = data[0];//this.adopter is undefined here. this refers to 'window'
            });
        }
    }

    $routerOnActivate(next) {
        if (next.params.id > 0) {
            this.getAdopterById(next.params.id);
        }
    }

    getAdopterById: (adopterId: number) => void;

    setAdopter(data: IAdopter) {
        this.adopter = data;//can access this.adopter
    }
}

Notice that the method declaration is empty and the implementation is set in the ctor using the arrow function. 请注意,方法声明为空,并且使用箭头函数在ctor中设置实现。

(2) (2)

class adopterDetailCtrl {
    public adopter: IAdopter;
    public $router: any;

    static $inject = ['app.common.services.AdopterService'];
    constructor(private adopterService: app.common.services.IAdopterServices) {
        this.adopter = null;

        this.getAdopterById = this.getAdopterById.bind(this);
    }

    $routerOnActivate(next) {
        if (next.params.id > 0) {
            this.getAdopterById(next.params.id);
        }
    }

    getAdopterById(adopterId: number): void {
        var AdopterList = this.adopterService.getAdopterById();
        AdopterList.query({ id: adopterId }, (data: adopter.IAdopter[]) => {
            this.adopter = data[0];//this.adopter is undefined here. this refers to 'window'
        });
    }

    setAdopter(data: IAdopter) {
        this.adopter = data;//can access this.adopter
    }
}

Here in the ctor you reassign the bound this.getAdopterById.bind(this) to this.getAdopterById . 在ctor中你将绑定的this.getAdopterById.bind(this)重新分配给this.getAdopterById

In both of these cases you can freely pass the getAdopterById method as a callback and not worrying about the scope of this . 在这两种情况下,您可以自由通过getAdopterById方法的回调,而不是担心的范围this

Another note on the arrow functions is that this is a new feature in ES6 , and if you don't choose the ES6 target in your compilation options then the compiler won't actually use this notation but instead will convert this: 关于箭头函数的另一个注意事项是这是ES6一个新功能,如果你没有在编译选项中选择ES6目标,那么编译器实际上不会使用这种表示法,而是会转换它:

class A {
    private x: number;

    fn(): void {
        setTimeout(() => console.log(this.x), 1);
    }
}

To: 至:

var A = (function () {
    function A() {
    }
    A.prototype.fn = function () {
        var _this = this;
        setTimeout(function () { return console.log(_this.x); }, 1);
    };
    return A;
}());

This way the scope of this is saved in _this and in the callback function _this.x is used instead of this.x . 这样的范围this是保存在_this并在回调函数_this.x代替this.x

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM