请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

深拷贝循环引用的问题

出现循环引用的时候会报错
index.js:23 Uncaught RangeError: Maximum call stack size exceeded

然后按照网上参考方案修改如下,并且想看看的老师的方案是怎样的:

/**
 * 深拷贝
 * @param {*} [obj={}] 要拷贝的对象
 * @param {*} [hash=new WeakMap()] 哈希表存储已拷贝过的对象
 * @returns
 */
function deepClone(obj = {}, hash = new WeakMap()) {
  if (typeof obj !== 'object' || obj == null) {
    // 不是引用类型或者null,直接返回
    return obj
  }
  if (hash.has(obj)) return hash.get(obj);
  // 初始化返回结果
  let result = obj instanceof Array ? [] : {}
  hash.set(obj, result);
  // 数组和对象都可以使用for in遍历
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 保证key不是原型上的key
      const element = obj[key];
      // 递归调用
      result[key] = deepClone(element, hash)
    }
  }
  return result
}

正在回答

2回答

做的很好,避免循环引用就是用 WeekMap 

2 回复 有任何疑惑可以回复我~
  • 老师,什么样的场景会出现循环引用?会导致什么问题呢?这里的weekMap作用是什么?能否讲解下?
    回复 有任何疑惑可以回复我~ 2020-03-13 23:30:44
  • 双越 回复 _123456789X #2
    类似 a = { b: b }; b = {a: a}; 这种循环引用的情况。
    回复 有任何疑惑可以回复我~ 2020-03-14 09:24:20
  • 提问者 光天化日之下 #3
    非常感谢!
    回复 有任何疑惑可以回复我~ 2021-06-13 09:42:29
RadiomM 2020-05-13 17:50:36

你这个写的是不是有问题呢? 为什么return的是 hash.get(obj)  你下面写入的不是一个空数组或者是一个空对象吗?

1 回复 有任何疑惑可以回复我~
  • 提问者 光天化日之下 #1
    前面是有判断条件的 hash.has(obj) 为true 才会 return has.get(obj)
    
    最上面两个if都不走的情况下,就可以确定这个是一个引用类型(对象或者数组),然后设置了一个临时的变量(一个空数组或者是一个空对象),并且把这个引用类型的变量存到WeakMap(因为我拷贝东西,肯定要东西放到一个新的变量result中)。
    
    在下面的 for (const key in obj) 循环中,会不断的递归。如果其中一个循环出现循环引用(也就是下面老师说的a = { b: b }; b = {a: a}),就需要使用缓存中的对象,跳出这次执行,继续下一个循环,否则就是死循环。
    回复 有任何疑惑可以回复我~ 2020-05-14 21:55:09
  • RadiomM 回复 提问者 光天化日之下 #2
    谢谢,我看错了。
    回复 有任何疑惑可以回复我~ 2020-05-14 22:50:00
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信