未定义的引用' this'在Typescript类中

时间:2017-04-04 19:25:50

标签: typescript nativescript

我在使用Typescript时遇到问题,其中this关键字在调试时显示为未定义,因此,不调用从回调方法调用的某些私有类方法。我的文本编辑器似乎认为我的引用很好并且给了我intellensense,所以我认为代码是可以的。下面是一个缩短的例子。调用cacheUser回调方法时,_processSuccessfulRegistration_handleCreationResponse不会被点击。

export class User extends Observable {
    public email: string;
    public password: string;
    public username: string

    constructor() {
        super()
        this.email = '';
        this.password = '';
        this.username = '';
    }

    public register() {
        let user = {
            // build out object
        }
        userService.createAccount(user)
            .catch(/* handle error */)
            .then(this._handleCreationResponse)
    }

    private _handleCreationResponse(response) {
        let status = response.status;
        let userData = response.result;

        switch (status) {
            case ApiStatus.Success:
                this._cacheUser(userData);
                this._processSuccessfulRegistration(userData);
                break;
            case ApiStatus.SomeError:
                // handle errors
                break;
            default:
                // do something else 
                break;
        }
    }

    private _cacheUser(user) {
        // handle user caching
    }

    private _processSuccessfulRegistration() {
        // call some other services and 
        // navigate to a new view
    }
}

1 个答案:

答案 0 :(得分:3)

当您将函数作为回调传递时,函数不会绑定到特定的this,因此当它们被执行时this将引用其他内容。

为避免您bind the function

userService.createAccount(user)
            .catch(/* handle error */)
            .then(this._handleCreationResponse.bind(this)

或使用arrow function确保为此保存正确的上下文:

userService.createAccount(user)
            .catch(/* handle error */)
            .then(response => this._handleCreationResponse(response))

修改

还有另一个选项是创建此方法作为箭头函数开始:

private _handleCreationResponse = (response) => {
    let status = response.status;
    let userData = response.result;

    switch (status) {
        case ApiStatus.Success:
            this._cacheUser(userData);
            this._processSuccessfulRegistration(userData);
            break;
        case ApiStatus.SomeError:
            // handle errors
            break;
        default:
            // do something else 
            break;
    }
}

然后你可以像以前那样传递它,并保留this的上下文 如果使用此选项,请注意它与之前的有点不同,因为_handleCreationResponse将不再是方法,而是实例的函数属性(也就是说,它不会是原型的一部分) )。

这是一个显示差异的简短示例:

class MyClass {
    method1() {
        console.log("method 1");
    }

    method2 = () => {
        console.log("method 2");
    }
}

编译为:

var MyClass = (function () {
    function MyClass() {
        this.method2 = function () {
            console.log("method 2");
        };
    }
    MyClass.prototype.method1 = function () {
        console.log("method 1");
    };
    return MyClass;
}());

你不能覆盖扩展类中箭头函数的方法,但是因为你的方法是私有的,所以它应该不是问题。