关于对象扁平化递归函数中展开运算符作用的疑问
对象扁平化递归中展开运算符的工作原理解析
先直接给你答案:...flatten(value)里的展开运算符,确实是展开flatten(value)返回的扁平化后的子对象,但绝对不会变成res={...res, ...res}——因为每次递归调用处理的是当前键对应的子对象,返回的是子对象扁平化后的新结果,和当前层的res完全是两个不同的对象。
拆解代码逻辑
这段代码的核心是递归遍历对象的每一层,把嵌套的键值对“拉平”到同一层级:
- 函数初始化一个空对象
res,用来存最终的扁平化结果。 - 循环遍历原对象的所有键值对:
- 如果当前值不是对象,直接把
key:value加到res里。 - 如果当前值是对象,就递归调用
flatten(value),把这个子对象先扁平化,再用展开运算符...把扁平化后的子对象的所有键值对,合并到当前层的res中。
- 如果当前值不是对象,直接把
用实例看过程
举个具体的嵌套对象例子,你就能直观理解:
const testObj = { a: 1, b: { c: 2, d: { e: 3 } } };
调用flatten(testObj)的执行步骤:
- 最外层调用:
res初始为空,先处理a:1,res变成{a:1}。 - 处理
b对应的子对象,调用flatten({c:2, d:{e:3}}):- 进入第一层递归:
res初始为空,先处理c:2,res变成{c:2}。 - 处理
d对应的子对象,调用flatten({e:3}):- 进入第二层递归:
res初始为空,处理e:3,res变成{e:3},返回这个对象。
- 进入第二层递归:
- 回到第一层递归,执行
res = {...{c:2}, ...{e:3}},得到{c:2, e:3},返回这个对象。
- 进入第一层递归:
- 回到最外层,执行
res = {...{a:1}, ...{c:2, e:3}},最终得到扁平化结果{a:1, c:2, e:3}。
纠正你的误解
你担心的res={...res, ...res}完全不会发生,因为:
- 当前层的
res是已经处理过的父级键值对集合(比如最外层的{a:1})。 flatten(value)返回的是子对象扁平化后的新对象(比如{c:2, e:3})。- 展开运算符的作用是把这两个对象的键值对合并成一个新对象,而不是重复展开同一个
res。
另外提个代码小问题:原代码里的console.log(flatten(value))会重复调用一次递归,平白增加性能开销,建议改成先把递归结果存起来再复用:
const flattenedChild = flatten(value); res = { ...res, ...flattenedChild }; console.log(flattenedChild);
内容的提问来源于stack exchange,提问作者Vaikruta
相关产品推荐
相关产品推荐

