首页 > 解决方案 > 如何删除此 for 循环并改用 array.some 函数?

问题描述

我有以下课程。我想将 filterOutEmails 函数转换为使用array.some而不是当前代码。

export class UsertableComponent {
  dataSource: MatTableDataSource<TrialUser>;


  createTableFromServer = (data: TrialUsers[], emailDomains:string) => {
    this.dataSource = new MatTableDataSource(data);
    this.dataSource.filterPredicate = this.filterOutEmails
  } 

  filterOutEmails = (row: TrialUser, emailDomains: string): boolean => {
    const listofFilters = emailDomains.split(',');
    for (let i = 0; i < listofFilters.length; i++){
      if (row.email.toLowerCase().includes(listofFilters[i].trim())){
        return true;
      };
    }
    return false;
  }
}

我尝试执行以下操作,但它给出this的是 null,当我尝试使用箭头函数时,我无法传入行。(如果我不设置为参数,那么“this”对应于 Type UsertableComponent,即函数所在的this: TrialUser类,即使我作为 thisObject 传入)rowsome

private determineIfRowShouldBeShown(this: TrialUser, domain: string): boolean {
  const row: TrialUser = this;
  return !row.email.toLowerCase().includes(domain.trim());
}

private filterOutEmails= (row: TrialUser, emailDomains: string): boolean {
  const listofFilters = emailDomains.split(',');
    return listofFilters.some(this.determineIfRowShouldBeShown, row) ;
  }
}

将“determineIfRowSHouldBeShown”作为内联粗箭头函数是可行的,但我想将函数定义分开。

标签: arraystypescriptfunctional-programming

解决方案


如果您使用箭头函数this,即使作为参数传递,也会在词法上绑定:

// If you're gonna abuse `this` I wouldn't put the function in a class as it's really confusing for `this` to not be the instance. You also can't use arrow functions in this case as they prevent rebinding the context.
function determineIfRowShouldBeShown(domain: string): boolean {
    return !this.email.toLowerCase().includes(domain.trim());
}

export class UsertableComponent {
  dataSource: MatTableDataSource<TrialUser>;

  createTableFromServer = (data: TrialUsers[], emailDomains:string) => {
      this.dataSource =  new MatTableDataSource(data);
      this.dataSource.filterPredicate = this.filterOutEmails
  }
  // I don't think this is a good name since it doesn't actually filter anything.
  filterOutEmails(row: TrialUser, emailDomains: string): boolean{
    return emailDomains.split(',').some(determineIfRowShouldBeShown, row);
  }
}

这也可以通过其他几种方式完成:

使用函数的手动绑定:

...
filterOutEmails(row: TrialUser, emailDomains: string){
  emailDomains.split(',').some(determineIfRowShouldBeShown.bind(row));
}

使用柯里化/部分应用程序(我的偏好)

const determineIfRowShouldBeShown = (row: TrialUser) => (domain: string): boolean => !row.email.toLowerCase().includes(domain.trim());
...
filterOutEmails(row: TrialUser, emailDomains: string){
  emailDomains.split(',').some(determineIfRowShouldBeShown(row));
}

推荐阅读