'this'在课堂上未定义

时间:2019-04-15 14:48:02

标签: javascript class asynchronous

看看下面的代码。

我正在使用构造函数创建一个类,并在其中创建一些变量。此外,我正在创建一些异步函数,其中三个非常相似,最后一个可以调用其他函数。

class Project {
    data = {};
    constructor(project, api) {
        for (const key in project) {
            this.data[key] = project[key];
        }
        this.logger = new Logger(
            document.querySelector("#output"),
            `Project= ${this.data.projectId}: `
        )
        this.api = api;
    }
    async getTasks() {
        return await this.api.getTasksAsync(this.projectId);
    }
    async getRequirements() {
        return await this.api.getRequirementsAsync(this.projectId);
    }
    async getReleases() {
        return await this.api.getReleasesAsync(this.projectId);
    }
    async getToDraw(type) {
        let func = this[`get${type}`];
        console.log(func);
        let result = [];
        for (let item of await func()){
            result.push(toTaskItem(item));
        }
        return result;
    }
}

在类“ Project”的启动对象上执行函数“ getToDraw”时出现的错误(如上所述): Error Pic

我按如下方式调用该函数:

async drawDiagram(sender){
    let projectID = this.getSelectedValue("projectSelector");
    if (projectID !== "-1") {
        let project = this.projects.filter((project) => project.data.ProjectId === parseInt(projectID))[0];
        if (document.querySelector("#typeSelector").selectedOptions[0].innerText === "Full"){
            // TODO: 
        } else {
            let list = await project.getToDraw(document.querySelector("#typeSelector").selectedOptions[0].innerText);
            console.log(list);
        }
    } else {
        for (let project of this.projects) {
            // TODO:
        }
    }
}

如果没有人知道我的解决方案,那么我已经知道我可以用另一种方式来解决,但是我想这样做...

Gracias,伙计们。

2 个答案:

答案 0 :(得分:4)

这是因为,当将getRequirements方法存储在func变量中时,会将其与上下文分开。

您必须再次将this上下文附加到func

第一种方式:仅附加一次上下文

您只需要像这样调用func函数:

func.call(this); // call func with this as context
func(); // call func with undefined context
func.call({}); // call func with empty object as context

这样,您可以强制使用func作为上下文来调用this

第二种方式:为所有将来的通话添加上下文

在调用函数之前,您必须先bind使用新上下文:

func(); // call func with undefined context
func = func.bind(this);
func(); // call func with this as context
func(); // recall func with this as context

通过这种方式,您可以将this链接为func的新上下文。

答案 1 :(得分:4)

看这行

let func = this[`get${type}`];

它将this引用中的函数解除绑定(或“断开连接”),以使您调用func()时,this成为undefined

有几种方法可以解决此问题。您可以使用bind重新绑定this,如下所示:

let func = this[`get${type}`].bind(this);

或者您可以在构造函数中显式重新绑定方法:

class Project {
  constructor(project, api) {
    ...
    this.getTasks = this.getTasks.bind(this);
    this.getRequirements = this.getRequirements.bind(this);
    this.getReleases = this.getReleases.bind(this);
  }
}

或者您可以将方法定义为lambda表达式属性,如下所示:

class Project {
  data = {};
  getTasks = () => { ... };
  getRequirements = () => { ... };
  getReleases = () => { ... };
}

当然,这些并不是唯一的解决方案,它们可能会有一些不同的副作用。例如,lambda表达式属性是可枚举的,因此它们将出现在Object.keys(new Project())中。