JavaScript assign函数如何基于keyPath创建嵌套对象?为何手动执行同逻辑结果不同?
核心原因:对象引用的特性 + 函数参数是值传递
你手动执行和函数执行的结果差异,本质是两个细节的共同作用:
- JavaScript中对象是引用类型,变量存储的是对象在内存中的地址,不是对象本身
- 函数的参数是值传递:你传入外层对象给函数的第一个参数
obj时,传递的是外层对象的内存地址拷贝,函数内部的obj是独立的局部变量,修改这个局部变量的指向,完全不会影响外层的原始变量。
函数执行的实际逻辑
假设你调用函数时传入的外层原始对象叫root = {}:
- 函数初始时,内部局部变量
obj和外层root指向同一个内存地址的空对象 - 循环每一步:先给当前
obj指向的对象创建不存在的嵌套属性,再把局部obj的指向修改为刚创建的内层嵌套对象,这个过程外层root的指向始终没变,它的嵌套结构在逐步被构建 - 循环结束时局部
obj指向keyPath倒数第二层的嵌套对象,给它赋值最后一个键值对,就直接写入了root的对应层级
你手动执行的问题
你手动写的代码里,始终用同一个变量obj存储最外层对象,每次执行obj = obj[key]都直接修改了这个最外层变量的指向,执行完循环后obj已经指向最内层的空对象了,你最后打印的就是这个内层对象,自然看不到完整的嵌套结构。你只要单独存储最外层对象的引用就能得到和函数一样的结果:
let root = {} // 用单独的变量遍历层级,不修改最外层root的指向 let current = root; let key; // 对应函数循环的第一次迭代 key = 'farm'; if (!(key in current)) { current[key] = {} } current = current[key]; // 第二次迭代 key = 'products'; if (!(key in current)) { current[key] = {} } current = current[key]; // 第三次迭代 key = '25'; if (!(key in current)) { current[key] = {} } current = current[key]; // 最后赋值 current['product name'] = 'lettuce'; console.log(JSON.stringify(root)); // 输出:{"farm":{"products":{"25":{"product name":"lettuce"}}}}
内容的提问来源于stack exchange,提问作者Dale Thompson
相关产品推荐
相关产品推荐

