如何在递归函数中调用另一个递归函数?解决TypeScript递归函数嵌套调用的undefined错误
解决递归函数调用中的
cannot read property 'date' of undefined错误 让我们一步步拆解你的问题,找出核心问题并逐一修复:
1. 触发错误的根本原因:this指向丢失
你遇到的cannot read property 'date' of undefined错误,本质是在递归调用过程中this的指向变成了undefined,导致无法访问类实例的date方法。这种情况通常发生在类方法没有正确绑定实例this,或者方法被当作普通函数调用时。
修复方案:稳定this指向
有两种简单的方式确保this始终指向类实例:
- 用箭头函数定义类方法:箭头函数会自动绑定当前实例的
this,彻底避免指向丢失:
export class FormFiller { fill = (index = 0): any => { // 原fill方法逻辑不变 } date = (qid: string, val?: string): any => { // 原date方法逻辑不变 } }
- 在构造函数中手动绑定
this:
export class FormFiller { constructor() { this.fill = this.fill.bind(this); this.date = this.date.bind(this); } fill(index = 0): any { /* ... */ } date(qid: string, val?: string): any { /* ... */ } }
2. 修复date方法的逻辑错误
除了this的问题,你的代码还有几个明显的逻辑漏洞,会导致后续报错:
- 未定义的
el变量:date方法里的$(el)是笔误,应该使用传入的qid参数来选择元素,即$(qid),否则根本找不到目标DOM元素。 - 缺少必填参数:
fill方法调用this.date()时,没有传递date要求的第一个参数qid,导致qid为undefined。你需要根据index传入对应的qid,比如维护一个qid列表:
// 假设你有需要处理的qid列表 private qids = ['input-1', 'input-2', 'input-3']; fill(index = 0): any { // 增加递归终止条件:遍历完所有qid if (index >= this.qids.length) { console.log('所有元素处理完成'); return; } const qid = this.qids[index]; const fillTypeFunction = this.date(qid); // 传入必填的qid参数 if (fillTypeFunction) { fillTypeFunction('arg1', 'arg2'); } else { console.warn(`无法获取元素处理函数,跳过qid: ${qid}`); } return this.fill(index + 1); }
date方法无返回值:当前date方法没有返回任何值,导致fillTypeFunction永远是undefined,会触发else分支的错误。如果你期望它返回可调用的处理函数,需要调整逻辑:
date(qid: string, val?: string): ((arg1: string, arg2: string) => void) | undefined { const elem = $(qid); // 先检查元素是否存在 if (!elem.length) { console.error(`找不到目标元素:${qid}`); return undefined; } if (elem.attr('ng-reflect-value')) { console.log(`元素${qid}已有值`); // 返回实际执行填充的函数 return (_, value) => { elem.val(value); console.log(`填充元素${qid}为:${value}`); }; } else { // 用定时器延迟递归,避免同步递归导致栈溢出 setTimeout(() => { this.date(qid, val); }, 200); return undefined; } }
- 无限递归风险:原
date方法没有终止条件,如果元素一直没有ng-reflect-value属性,会无限递归导致栈溢出。添加定时器延迟递归是一种缓解方式,你也可以增加递归次数限制来彻底避免。
3. 完整修复后的代码示例
export class FormFiller { private qids = ['input-1', 'input-2', 'input-3']; constructor() { this.fill = this.fill.bind(this); this.date = this.date.bind(this); } fill(index = 0): any { if (index >= this.qids.length) { console.log('所有元素填充完成'); return; } const qid = this.qids[index]; const fillTypeFunction = this.date(qid); if (fillTypeFunction) { fillTypeFunction('arg1', 'sample-value'); } else { console.warn(`跳过元素${qid}:无法获取处理函数`); } return this.fill(index + 1); } date(qid: string, val?: string): ((arg1: string, arg2: string) => void) | undefined { const elem = $(qid); if (!elem.length) { console.error(`元素${qid}不存在`); return undefined; } if (elem.attr('ng-reflect-value')) { return (_, value) => { elem.val(value); console.log(`元素${qid}填充完成,值为:${value}`); }; } else { setTimeout(() => { this.date(qid, val); }, 200); return undefined; } } }
内容的提问来源于stack exchange,提问作者Ara Galstyan
相关产品推荐
相关产品推荐

