Skip to content

deepClone 深拷贝

js
// 解决循环引用的方案
// https://www.jianshu.com/p/93bc862e8e0d
// 弱引用
// https://github.com/chaos-zhu/Es5678910-study/issues/5

// JSON.parse(JSON.stringify(obj))  缺陷:1、无法处理函数、symbol、正则;2、循环引用报错
function deepClone(obj, map = new WeakMap()) {
    if(typeof(obj) !== 'object' || typeof(obj) === null) return obj
    if(obj instanceof Function) return obj
    if(obj instanceof RegExp) return obj
    if(obj instanceof Date) return obj
    // 解决循环引用的问题
    if(map.get(obj)) return obj
    map.set(obj, obj)
    let res = Array.isArray(obj) ? [] : {}
    for(let key in obj) {
        if(obj.hasOwnProperty(key)) res[key] = deepClone(obj[key], map)
    }
    return res
}

let obj1 = {
    name: 'tom',
    age: 19,
    other: {
        city: ['sz', "gg"],
        sex: 'man'
    },
    fn: function () {return 1},
    date: new Date(),
    sym: Symbol(),
    reg: new RegExp('\\w+'),
}
let obj2 = deepClone(obj1)
obj1.name = 'chaos'
obj1.other.city[1] = 'hz'
obj1.other.sex = 'woman'

console.log(obj2)

判断更简单点的版本

js
function type(val) {
  const [, res] =  Object.prototype.toString.call(val).match(/\[object\s(.+)\]/) // 加g修饰符返回的又是另外一个结果了https://chaoszhu.com/front-end/regexp/js%E5%B8%B8%E7%94%A8%E6%AD%A3%E5%88%99API.html#match-%E5%92%8C-matchall
  return res.toLowerCase()
}
// console.log(type(''))

function deepClone(obj, map = new WeakMap()) {
  console.log(type(obj))
  if(!(['object', 'array'].includes(type(obj)))) return obj // 获取直接判断: !(Array.isArray(obj) || typeof(obj) === 'object')
  if(map.get(obj)) return obj
  map.set(obj, obj)
  let res = Array.isArray(obj) ? [] : {}
  for (const key in obj) {
    console.log(obj[key])
    if(obj.hasOwnProperty(key)) res[key] = deepClone(obj[key], map)
  }
  return res
}

let o = {
  a: 1,
  b: {a: 2},
  c: new Date(),
  d: new RegExp('/a/'),
  f: () => {}
}

let deepO = deepClone(o)

console.log(deepO === o)