使用recursive-iterator迭代对象时报错:无法解构未定义的valueOnDeepClone
问题根因
报错的核心原因是两个迭代器遍历步调不一致:旧对象中的modifiedProperties是空数组,迭代器不会进入数组内部遍历;新对象中的modifiedProperties是带元素的非空数组,迭代器会额外遍历数组内的每一项,导致新对象迭代器比旧对象多走若干步,旧对象先遍历完成后next()返回的value为undefined,解构属性时就会抛出类型错误。
解决方案
方案1:配置迭代器过滤规则
RecursiveIterator第二个参数支持传入自定义过滤函数,返回false的节点不会进入递归遍历,我们可以直接跳过modifiedProperties属性,保证两个迭代器步调完全一致:
// 自定义过滤器:跳过modifiedProperties属性的递归遍历 const traverseFilter = (node: any, key: string | number) => { return key !== 'modifiedProperties'; } const iteratorOnDeepClone = new RecursiveIterator(old, traverseFilter, true); const iteratorOnModifiedObject = new RecursiveIterator(n, traverseFilter, true);
如果你的遍历逻辑不需要处理数组类型,也可以在过滤规则中增加Array.isArray(node) && return false的判断,进一步避免类似的步调不一致问题。
方案2:补充迭代完成状态判断
调整循环逻辑,优先判断两个迭代器的done标记,只要任意一个迭代完成就直接退出循环,避免访问undefined的返回值:
while (true) { const { value: valueOnModifiedObject, done: doneOnModifiedObject } = iteratorOnModifiedObject.next(); const { value: valueOnDeepClone, done: doneOnDeepClone } = iteratorOnDeepClone.next(); // 任意迭代器遍历完成即退出 if (doneOnModifiedObject || doneOnDeepClone) { console.log("done!"); break; } // 原有业务逻辑 const { parent: parentOnDeepClone, node: nodeOnDeepClone, key: keyOnDeepClone, path: pathOnDeepClone, deep: deepOnDeepClone } = valueOnDeepClone; const { parent: parentOnModifiedObject, node: nodeOnModifiedObject, key: keyOnModifiedObject, path: pathOnModifiedObject, deep: deepOnModifiedObject } = valueOnModifiedObject; if (nodeOnModifiedObject.modifiedProperties != undefined) { for (const prop of nodeOnModifiedObject.modifiedProperties) { const oldValue = nodeOnDeepClone[prop]; console.log(prop, oldValue); } } }
方案3:优化实现逻辑避免同步问题
如果你的核心需求只是获取修改属性对应的旧值,不需要同时运行两个迭代器,只需要遍历修改后的对象,根据节点路径直接从旧对象中取值即可:
// 辅助函数:根据路径从对象中读取对应值 const getValueByPath = (obj: any, path: Array<string | number>) => { return path.reduce((current, key) => current?.[key], obj); } const traverseFilter = (node: any, key: string | number) => key !== 'modifiedProperties'; const iteratorOnModifiedObject = new RecursiveIterator(n, traverseFilter, true); for (const { node, path } of iteratorOnModifiedObject) { if (!node.modifiedProperties) continue; const oldNode = getValueByPath(old, path); for (const prop of node.modifiedProperties) { console.log(prop, oldNode?.[prop]); } }
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

