如何深克隆一个对象

我们在实际开发中,经常需要深拷贝一个对象,我一般喜欢使用JSON.parse(JSON.stringify()) ,方便好用。不过如果对象的value值为 SymbolFunctionundefined 时,这些值就会被忽略。
比如

const obj = {
	a: Symbol(2),
	b: undefined,
	c: () => {},
	d: 3
}
JSON.parse(JSON.stringify(obj)) // {d: 3}

还有如果value值不是一个普通的对象,而是一个Map或者Set对象,用上面的方法就会拷贝成一个普通的对象。所以在面对一些特殊情况下时,就不太好用了。下面写下我在特殊情况下使用的方法


function deepClone(obj, hash = new WeakMap()) {
// 如果对象的值等于它本身,在递归的时候会陷入死循环,通过WeakMap模拟hash表,避免这种情况的出现
  if (hash.has(obj)) return hash.get(obj)
  let type = Object.prototype.toString.call(obj)
  let target;
  switch (type) {
  	// 普通对象需要考虑下key值为Symbol的情况
    case "[object Object]":
      let symKeys = Object.getOwnPropertySymbols(obj)
      target = {}
      if (symKeys.length) {
        symKeys.forEach(key => {
          target[key] = deepClone(obj[key], hash)
        })
      }
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (typeof obj[key] === 'object') {
            target[key] = deepClone(obj[key], hash)
          } else {
            target[key] = obj[key]
          }
        }
      }
      break;
    case "[object Array]":
      target = []
      obj.forEach(val => {
        if (typeof val === 'object') {
          target.push(deepClone(val, hash))
        } else {
          target.push(val)
        }
      })
      break;
    case "[object Map]":
      // 调用map对象的forEach方法遍历所有的键值对
      target = new Map()
      obj.forEach((val, key) => {
        target.set(key, deepClone(val, hash))
      })
      break;
    case "[object Set]":
      target = new Set()
      obj.forEach(val => {
        target.add(deepClone(val, hash))
      })
      break;
    case "[object Date]":
      target = new Date(obj)
      break;
    default:
      target = obj
      break;
  }
  return target
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值