Angular中排序函数调用自定义比较函数报错:Cannot read property 'compareAddresses' of undefined问题排查
解决Angular中排序函数调用自定义比较方法时
this指向丢失的问题 这个错误的核心原因是函数上下文丢失:当你把sortByTown作为参数传递给Array.sort()时,这个函数的this不再指向你的Angular组件实例,而是变成了undefined(严格模式下),所以调用this.compareAddresses时就会抛出“Cannot read property 'compareAddresses' of undefined”的错误。
下面给你几种可行的解决方案,从简单到进阶:
方案1:在构造函数中绑定this
在组件的构造函数里,手动将排序方法的this绑定到组件实例,确保上下文不会丢失:
constructor() { // 为每个排序方法绑定this this.sortByTown = this.sortByTown.bind(this); this.sortByStreet = this.sortByStreet.bind(this); this.sortByPostcode = this.sortByPostcode.bind(this); this.sortByCountry = this.sortByCountry.bind(this); } sortByTown(address1: any, address2: any): number { const a = address1.town.toUpperCase(); const b = address2.town.toUpperCase(); return this.compareAddresses(a, b); } // 其他3个排序方法逻辑类似... compareAddresses(a: string | number, b: string | number): number { if (a > b) { return 1; } else if (a < b) { return -1; } return 0; }
方案2:用箭头函数定义排序方法
箭头函数会自动捕获当前上下文的this,不会出现丢失问题,直接把排序方法改成箭头函数即可,这也是Angular中处理这类问题的常用方式:
// 用箭头函数定义,this自动指向组件实例 sortByTown = (address1: any, address2: any): number => { const a = address1.town.toUpperCase(); const b = address2.town.toUpperCase(); return this.compareAddresses(a, b); }; sortByStreet = (address1: any, address2: any): number => { const a = address1.street.toUpperCase(); const b = address2.street.toUpperCase(); return this.compareAddresses(a, b); }; // 另外两个排序方法同理... compareAddresses(a: string | number, b: string | number): number { if (a > b) { return 1; } else if (a < b) { return -1; } return 0; }
方案3:进阶优化——通用排序函数生成器
既然你有4个类似的排序方法,完全可以再进一步封装,用一个工厂函数生成所有排序方法,彻底遵循DRY原则:
// 通用排序函数生成器,传入属性名即可生成对应的排序函数 private createSortFn(property: string) { return (address1: any, address2: any): number => { // 兼容字符串和数字类型的属性 const a = typeof address1[property] === 'string' ? address1[property].toUpperCase() : address1[property]; const b = typeof address2[property] === 'string' ? address2[property].toUpperCase() : address2[property]; return this.compareAddresses(a, b); }; } // 一行代码初始化一个排序方法 sortByTown = this.createSortFn('town'); sortByStreet = this.createSortFn('street'); sortByPostcode = this.createSortFn('postcode'); sortByCountry = this.createSortFn('country'); compareAddresses(a: string | number, b: string | number): number { if (a > b) { return 1; } else if (a < b) { return -1; } return 0; }
这样你只需要写一次生成逻辑,所有排序方法都可以复用,后续新增排序属性也只需要一行代码。
不管用哪种方案,核心都是确保排序函数里的this指向你的组件实例,这样就能正确调用compareAddresses方法了。
内容的提问来源于stack exchange,提问作者Gentem
相关产品推荐
相关产品推荐

