guapi233
  • 2
  • 新人请关照

实现JS深拷贝时出现的一个问题?

function extendDeep() {
  let deep = false, args = Array.from(arguments)

  if (typeof arguments[0] === "boolean") {
      deep = args.shift()
  }
  
  target = args.shift()

  args.forEach(item => {
      for (let i in item) {

          if (typeof item[i] === "object" && deep) {
              // 这里出了问题 ↓ 明明把递归后组合的对象赋值给了target["b"],却导致target自身被覆盖了
              console.log("递归之前:", target, i)
              target[i] = extendDeep(deep, target[i], item[i])
              console.log("递归之后:", target)
          } else {
              target[i] = item[i]
          }
      }
  })

  return target
}



// -----------------------------------------------


var obj1 = {
  a: 1,
  b: { b1: 1, b2: 2 }
};

var obj2 = {
  b: { b1: 3, b3: 4 },
  c: 3
};

var obj3 = {
  d: 4
}

console.log("最终结果:", extendDeep(true, obj1, obj2, obj3));

result.png

期望的结果是第二个打印为 递归之后:{a:1, b:{b1:3, b2:2, b3: 4}}

底子比较薄弱,第一次碰到这种问题,完全没有头绪哪里出错了,望大佬提点o(╥﹏╥)o

阅读 126
评论
    2 个回答

    函数内声明一下target,不然变成全局变量共用了。

      let deep = false, args = Array.from(arguments), target;
    评论 赞赏

      方法传参要注意对象和数组都是地址传参,你的传参都是原始对象传进去,自然改变了改变原来对象的值。你可以修改传参方式如:

      target[i] = extendDeep(deep, {...target[i]}, item[i])

      在需要的地方用析构重新创建一个对象进去,就不会修改外面的对象了。

      另外这种深拷贝可以使用插件去完成,不需要自己再去造轮子。如果是自己学习,那另当别论了。

      评论 赞赏
        撰写回答

        登录后参与交流、获取后续更新提醒