【问题标题】:Angular2 component's "this" is undefined when executing callback functionAngular2组件的“this”在执行回调函数时未定义
【发布时间】:2016-11-09 18:30:03
【问题描述】:

我有一个组件调用服务从 RESTful 端点获取数据。该服务需要在获取数据后执行回调函数。

问题是当我尝试使用回调函数将数据附加到组件变量中的现有数据时,我得到了一个EXCEPTION: TypeError: Cannot read property 'messages' of undefined。为什么this 未定义?

TypeScript 版本:1.8.10 版

控制器代码:

import {Component} from '@angular/core'
import {ApiService} from '...'

@Component({
    ...
})
export class MainComponent {

    private messages: Array<any>;

    constructor(private apiService: ApiService){}

    getMessages(){
        this.apiService.getMessages(gotMessages);
    }

    gotMessages(messagesFromApi){
        messagesFromApi.forEach((m) => {
            this.messages.push(m) // EXCEPTION: TypeError: Cannot read property 'messages' of undefined
        })
    }
}

【问题讨论】:

  • 您使用的是哪个版本的 TypeScript? (您可以使用tsc -v 进行检查)
  • 异常是因为 forEach.请改用 For-of。

标签: javascript arrays typescript angular


【解决方案1】:

使用Function.prototype.bind函数:

getMessages() {
    this.apiService.getMessages(this.gotMessages.bind(this));
}

这里发生的情况是您将 gotMessages 作为回调传递,当执行该回调时,范围不同,因此 this 不是您所期望的。
bind 函数返回一个绑定到您定义的 this 的新函数。

当然,您也可以在那里使用arrow function

getMessages() {
    this.apiService.getMessages(messages => this.gotMessages(messages));
}

我更喜欢 bind 语法,但这取决于你。

第三个选项,以便绑定方法开始:

export class MainComponent {
    getMessages = () => {
        ...
    }
}

或者

export class MainComponent {
    ...

    constructor(private apiService: ApiService) {
        this.getMessages = this.getMessages.bind(this);
    }

    getMessages(){
        this.apiService.getMessages(gotMessages);
    }
}

【讨论】:

  • 工作,谢谢!感谢您解释为什么会发生这种情况。
  • 谢谢! OOP 样式泄漏 javascript 细节(绑定)的事实是可悲的。
  • 完全同意@skfd .bind( this ) 应该是默认的 TypeScript 行为,因为我们正在编程 OO! :-) 但是谢谢,我会记得现在将它添加到类成员函数的所有回调中,这在我的情况下总是如此,因为 ...
【解决方案2】:

或者你可以这样做

gotMessages(messagesFromApi){
    let that = this // somebody uses self 
    messagesFromApi.forEach((m) => {
        that.messages.push(m) // or self.messages.push(m) - if you used self
    })
}

【讨论】:

  • 你是我的英雄
【解决方案3】:

因为您只是在 getMessages 中传递函数引用,所以您没有正确的 this 上下文。

您可以通过使用自动绑定正确的 this 上下文以在该匿名函数中使用的 lambda 轻松解决此问题:

getMessages(){
    this.apiService.getMessages((data) => this.gotMessages(data));
}

【讨论】:

  • 就是这样!谢谢
  • 完美。最简单高效的解决方案。
【解决方案4】:

我有同样的问题,通过使用 () => { } 解决了 function()

【讨论】:

  • 这不会向现有答案添加任何信息
【解决方案5】:

请定义函数

gotMessages = (messagesFromApi) => {
  messagesFromApi.forEach((m) => {
    this.messages.push(m)
  })
}

【讨论】:

  • 这不会向现有答案添加任何信息
猜你喜欢
  • 2020-05-05
  • 2016-08-21
  • 2017-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多