为何无法用filter移除数组中的绑定类方法?
问题原因与解决方案
根本原因不是作用域问题,而是**bind()方法的特性**:每次调用Function.prototype.bind()都会返回一个全新的函数实例——哪怕你绑定的是同一个原函数和同一个this上下文,两次bind的结果也不是同一个引用。
你代码里的问题:
- 推送到数组的是第一次
bind生成的函数A - 过滤时用的是第二次
bind生成的函数B - A和B是两个不同的对象,全等判断
f !== B永远为true,所以原函数A不会被过滤掉
解决方法
1. 提前保存绑定后的函数引用(推荐)
把绑定后的函数存为实例属性,复用这个引用做添加和移除操作:
let array: any[] = []; class Test { private boundTestMethod: () => void; constructor() { // 只绑定一次,保存引用 this.boundTestMethod = this.testMethod.bind(this); array.push(this.boundTestMethod); console.log('xxx', array); // [ [Function: bound ] ] // 用保存的引用做过滤判断 array = array.filter(f => f !== this.boundTestMethod); console.log('xxx', array); // [] } public testMethod(): void { return undefined; } }
2. 使用箭头函数替代bind(类场景下更简洁)
在类中用箭头函数定义方法,箭头函数会自动捕获当前实例的this上下文,且整个实例生命周期内是同一个函数引用:
let array: any[] = []; class Test { // 直接用箭头函数定义,自动绑定this public testMethod = (): void => { return undefined; } constructor() { array.push(this.testMethod); console.log('xxx', array); // [ [Function (anonymous)] ] array = array.filter(f => f !== this.testMethod); console.log('xxx', array); // [] } }
3. 特殊场景下的备选方案(不推荐)
如果无法提前保存引用,可以通过函数的name属性(绑定后的函数name为bound testMethod)或者自定义标识来匹配,但这种方法风险高——如果数组中有多个来自同一个原函数的绑定实例,会误删所有匹配项:
// 仅作演示,不推荐在生产环境使用 array = array.filter(f => f.name !== 'bound testMethod');
内容的提问来源于stack exchange,提问作者Kris
相关产品推荐
相关产品推荐

