递归函数修改JavaScript对象为何能同步至原对象?
递归修改对象路径值:引用传递的原理
你这个问题的核心是JavaScript引用类型的传参机制,下面直接拆解清楚:
递归中object变量的关联
JavaScript里的对象(包括数组)属于引用类型,它们在内存中存储的是数据的地址,而非数据本身。当你把对象作为参数传给函数时,传递的是这个内存地址的引用,不是整个对象的拷贝:
- 第一次调用
objWalker时,object变量是testObject的引用,指向原对象在内存中的位置。 - 递归调用
objWalker(object[pathArr[0]], ...)时,object[pathArr[0]]是原对象里的嵌套对象(比如第一次递归里的testObject.abc),它本身也是一个引用。新递归调用里的object变量是作用域内的独立变量,但它和上层的object[pathArr[0]]指向同一个内存地址里的对象。 - 每一层递归的
object变量都是独立的,但它们指向的是原对象嵌套结构里的同一个子对象/数组。
为什么修改能反映到原对象
当递归走到最后一层(pathArr.length === 1),执行object[path] = payload时:
- 这里的
object是原对象嵌套结构里的目标子对象(比如例子里的testObject.abc.def),它是原对象对应部分的引用。 - 修改这个引用指向的对象的属性,本质就是直接修改原对象在内存中的数据,所以原对象
testObject会同步看到变化。
结合你的代码走一遍流程
以objWalker(testObject, "abc.def.ghi", { new: "element" })为例:
- 第一次调用:拆分
path得到["abc","def","ghi"],递归调用objWalker(testObject.abc, "def.ghi", ...),此时新的object指向testObject.abc。 - 第二次调用:拆分
path得到["def","ghi"],递归调用objWalker(testObject.abc.def, "ghi", ...),新的object指向testObject.abc.def。 - 第三次调用:拆分
path得到["ghi"],执行object["ghi"] = { new: "element" },这里的object就是testObject.abc.def,修改它的ghi属性,直接改变了原testObject里的对应值。
补充:如果是字符串、数字这类原始类型,传参是值传递,修改不会影响上层,但你的场景里都是对象/数组,所以是引用传递的逻辑生效。
内容的提问来源于stack exchange,提问作者ritwick_ _D
相关产品推荐
相关产品推荐

