TypeScript:解决作为函数对象传递的方法无法访问类成员问题
问题:传递类方法作为参数时丢失this上下文,无法访问类属性
需求是编写通用代码将函数作为参数传递给另一个函数,实际参数要在接收函数内部计算得出,但当前代码中传递类方法add时,方法内部的this指向丢失,导致报错:
Error: Cannot read properties of undefined (reading 'zopa')
原代码如下:
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'hello', template: `<h1>Hello {{name}}!</h1>`, styles: [`h1 { font-family: Lato; }`], }) export class HelloComponent implements OnInit { @Input() name: string; private zopa = new Zopa(); ngOnInit() { let addResult = this.methodCaller(this.add); console.log('Add Result: ', addResult); let subtractResult = this.methodCaller(this.subtract); console.log('Subtract Result: ', subtractResult); } methodCaller(method) { const x = 5; const y = 4; return method(x, y); } add(a, b) { console.log('add method calling ', this.zopa.prop); return a + b; } subtract(a, b) { console.log('subtract method calling... '); return a - b; } } class Zopa { prop = 'zopa'; }
本质问题是:传递add作为函数对象时,this的上下文没有绑定到HelloComponent实例,导致在methodCaller中调用method(x,y)时,add内部的this为undefined(严格模式下)。
解决方案
有三种常见方式可以解决这个this上下文丢失的问题:
1. 传递方法时用bind绑定this
在调用methodCaller时,通过bind把当前实例的this绑定到add和subtract方法上:
ngOnInit() { let addResult = this.methodCaller(this.add.bind(this)); console.log('Add Result: ', addResult); let subtractResult = this.methodCaller(this.subtract.bind(this)); console.log('Subtract Result: ', subtractResult); }
bind会返回一个新函数,这个新函数的this会永久绑定到指定的上下文(这里是HelloComponent实例),后续调用时不会丢失。
2. 使用箭头函数定义类方法
箭头函数的this会继承自定义时的上下文,也就是类实例本身,这样传递方法时不会丢失this:
// 修改add和subtract为箭头函数 add = (a, b) => { console.log('add method calling ', this.zopa.prop); return a + b; } subtract = (a, b) => { console.log('subtract method calling... '); return a - b; } // ngOnInit中无需额外处理,直接传递方法 ngOnInit() { let addResult = this.methodCaller(this.add); console.log('Add Result: ', addResult); let subtractResult = this.methodCaller(this.subtract); console.log('Subtract Result: ', subtractResult); }
3. 在methodCaller中调用方法时用call/apply指定this
修改methodCaller方法,调用传入的函数时通过call或apply把当前实例的this传递进去:
methodCaller(method) { const x = 5; const y = 4; // 使用call指定this为当前组件实例 return method.call(this, x, y); // 或者用apply,参数以数组形式传递:method.apply(this, [x, y]) } // ngOnInit中依然直接传递方法即可 ngOnInit() { let addResult = this.methodCaller(this.add); console.log('Add Result: ', addResult); let subtractResult = this.methodCaller(this.subtract); console.log('Subtract Result: ', subtractResult); }
这三种方式都能让add和subtract方法内部正确访问到this.zopa.prop,可以根据实际场景选择合适的方案。
内容的提问来源于stack exchange,提问作者Pradip
相关产品推荐
相关产品推荐

