【问题标题】:Undefined reference to 'this' in Typescript classTypescript 类中对“this”的未定义引用
【发布时间】:2017-04-04 19:25:50
【问题描述】:

我在使用 Typescript 时遇到问题,其中 this 关键字在调试时显示为未定义,因此没有调用我的一些从回调方法调用的私有类方法。我的文本编辑器似乎认为我的参考很好并且给了我智能,所以我认为代码没问题。下面是一个简短的例子。调用 _handleCreationResponse 回调方法时,cacheUser_processSuccessfulRegistration 不会受到影响。

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
    }
}

【问题讨论】:

    标签: typescript nativescript


    【解决方案1】:

    当您将函数作为回调传递时,函数不会绑定到特定的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;
    }());
    

    您不能在扩展类中覆盖箭头函数的方法,但由于您的方法是私有的,所以这应该不是问题..

    【讨论】:

    • 绝妙的答案!一个问题是我不需要做.then((response)=>{this._handleUserCreateResponse(response)}) 以获得箭头函数方法以将响应传递给私有方法吗?这似乎是让它为我工作的唯一方法。
    • 是的,你是对的。我的错,但我编辑了它,现在已经修好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多