deepClone 实现深拷贝对象

366 阅读1分钟

背景

在日常开发中,可能需要赋值一个对象;但是对象的赋值是将一个对象的引用赋值给另一个变量,是浅拷贝

let obj = { name: '张三', num: 5 }
let o = obj
o.num = 10

console.log('o:', o, 'obj:', obj) // obj.num = 10
console.log('o == obj:', o == obj) // true

image.png

但是我们的目的是修改赋值后的变量的属性值,不影响引用赋值的对象属性值。

解决方法

通过深拷贝,改变引入地址来解决

JSON

通过 JSON.parse(JSON.stringify()) 来实现深度拷贝。但是不能处理函数、undefined 值、循环引用

let obj = { name: '张三', num: 5 }
let o = JSON.parse(JSON.stringify(obj))
o.num = 10

console.log('o:', o, 'obj:', obj) // obj.num = 5
console.log('o == obj:', o == obj) // false

image.png

但是不能处理函数、undefined 值、循环引用。

let obj = {
    name: '张三', 
    num: null, 
    count: undefined, 
    fn: function () {
        console.log('function')
    }
}
let o = JSON.parse(JSON.stringify(obj))

console.log('o:', o) 

image.png

deepClone

通过递归循环对象的属性值,将键值对赋值给新的变量

实现:

function deepClone(source) {
  if (!source || typeof source !== 'object') {
    return source
  }

  const targetObj = Array.isArray(source) ? [] : {}
  for (let key in source) {
    if (source[key] && typeof source[key] === 'object') {
      targetObj[key] = deepClone(source[key])
    } else {
      targetObj[key] = source[key]
    }
  }
  return targetObj
}

使用:

let obj = { name: '张三', num: 5 }
let o = deepClone(obj)
o.num = 10

console.log('o:', o, 'obj:', obj) // obj.num = 5
console.log('o == obj:', o == obj) // false

image.png