看看下面的代码。
我正在使用构造函数创建一个类,并在其中创建一些变量。此外,我正在创建一些异步函数,其中三个非常相似,最后一个可以调用其他函数。
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”时出现的错误(如上所述):
我按如下方式调用该函数:
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,伙计们。
答案 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())
中。