Angular同类别函数间变量访问问题及代码重构咨询
解决方法:让
evaluateResult访问execute中的namesSplit变量 嘿,作为初学者碰到这种作用域问题太正常了,我给你两种清晰的重构方案,顺便还会修正代码里的小bug,帮你彻底搞定:
方案1:直接传递namesSplit作为参数(推荐,无状态残留)
这是最直接且安全的方式——既然execute主动调用evaluateResult,那直接把namesSplit当作参数传过去就行,完全不需要修改类的状态:
首先修改execute里的调用逻辑:
if (namesSplit.length > 1) { this.evaluateResult(contextEntry.value, namesSplit); }
然后更新evaluateResult的定义和内部逻辑,同时修正原代码里的几个明显问题:
evaluateResult(val: any, namesSplit: string[]) { if (this.getType(val) === ExpressionVariableType.OBJECT) { return Object.values(val); } else if (this.getType(val) === ExpressionVariableType.ARRAY_OF_OBJECTS) { for (let obs of val) { // 修正:原逻辑里直接拿字符串和数组比较是错误的,改成检查对象是否包含目标key const targetKey = namesSplit[0]; // 按你原逻辑的意图,取分割后的第一个key if (obs.hasOwnProperty(targetKey)) { let result = Object.values(obs[targetKey]); console.log(result); break; } } } else if (this.getType(val) === ExpressionVariableType.ARRAY_OF_PRIMITIVES) { throw new StdException('Array of Primitives not allowed!'); } else if (this.getType(val) === ExpressionVariableType.PRIMITIVE) { throw new StdException('Primitive values not allowed!'); // 修正拼写错误:Primtive → Primitive } }
方案2:将namesSplit设为类的实例属性(适合多方法复用场景)
如果你的类需要在多个方法里复用namesSplit,可以把它定义成类的实例变量,但要注意状态残留问题(如果同一个实例多次调用execute,namesSplit会被覆盖):
首先在类里添加实例属性:
export class ExecutableVariableNode implements IExecutableNode { private namesSplit?: string[]; // 定义实例变量,用?标记为可选 // ... 其他方法保持不变 }
然后在execute里给这个变量赋值:
execute(treeNode: ExpressionTreeNode, exprData: ExpressionData): any { this.namesSplit = treeNode.name.split('.'); // 赋值给实例变量 let key = this.namesSplit[0]; let contextEntry = exprData.contextEntry.find(_x => _x.name === key); if (this.namesSplit.length > 1) { this.evaluateResult(contextEntry.value); } }
最后在evaluateResult里直接使用this.namesSplit,记得加安全校验:
evaluateResult(val: any) { if (!this.namesSplit) { throw new Error('namesSplit has not been initialized!'); // 防止未赋值就调用 } if (this.getType(val) === ExpressionVariableType.OBJECT) { return Object.values(val); } else if (this.getType(val) === ExpressionVariableType.ARRAY_OF_OBJECTS) { for (let obs of val) { const targetKey = this.namesSplit[0]; if (obs.hasOwnProperty(targetKey)) { let result = Object.values(obs[targetKey]); console.log(result); break; } } } else if (this.getType(val) === ExpressionVariableType.ARRAY_OF_PRIMITIVES) { throw new StdException('Array of Primitives not allowed!'); } else if (this.getType(val) === ExpressionVariableType.PRIMITIVE) { throw new StdException('Primitive values not allowed!'); } }
额外提示
原代码里还有几个小细节需要调整:
LapsExpressionVariableType看起来是笔误,建议和前面的ExpressionVariableType保持一致- 原逻辑里
namesSplit[n] == Object.keys(obs)完全错误,因为Object.keys(obs)返回的是数组,不能直接和字符串比较,我在上面的代码里已经修正了这个逻辑
内容的提问来源于stack exchange,提问作者OTRAY
相关产品推荐
相关产品推荐

