【问题标题】:How do I remove this for loop and use the array.some function instead?如何删除此 for 循环并改用 array.some 函数?
【发布时间】:2020-02-08 07:21:55
【问题描述】:

我有以下课程。我想将 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 为空,当我尝试使用箭头函数时,我无法通过行。 (如果我没有将this: TrialUser 设置为参数,那么“this”对应于Type UsertableComponent,即函数所在的类,即使我将row 作为thisObject 传递给some

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”作为内联粗箭头函数是可行的,但我想将函数定义分开。

【问题讨论】:

标签: arrays typescript functional-programming


【解决方案1】:

如果你使用箭头函数 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));
}

【讨论】:

  • 打字稿编译器不喜欢这样:ERROR in app/trialusers/usertable/usertable.component.ts:65:18 - error TS2339: Property 'email' does not exist on type 'UsertableComponent'. return !this.email.toLowerCase().includes(domain.trim()); UserTableComponent 是这个函数所在的类。
  • 我想我可能误解了这些方法所在的类以及它们之间的关系。你能提供更多背景信息吗?
  • 更新了上下文。
  • 谢谢。柯里化解决方案是我一直在寻找的。令人惊讶的是,如果您不对 thisArg 进行强制转换,使用 bind 会导致相同的编译器错误。
猜你喜欢
  • 1970-01-01
  • 2022-01-17
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
相关资源
最近更新 更多