对象深拷贝的两种实现方式(深度优先,广度优先)

话不多说,直接上代码


const _toString = Object.prototype.toString
function getType(obj) {
  return _toString.call(obj).slice(8, -1)
}


function DFSDeepClone(obj, vistied = new Set(), level = 0) {
  let res = {}

  if (getType(obj) === 'Object' || getType(obj) === 'Array') {
    if (vistied.has(obj)) {
      // 处理环状结构
      res = obj
    } else {
      vistied[level] = obj
      vistied.add(obj)
      res = getType(obj) === 'Object' ? {} : []
      Object.keys(obj).forEach(k => {
        res[k] = DFSDeepClone(obj[k], vistied, level + 1)
      })
    }
  } else if (typeof obj === 'function') {
    res = eval(`(${obj.toString()})`)
  } else {
    res = obj
  }

  return res
}


function BFSDeepClone(obj) {
  if (getType(obj) !== 'Object' && getType(obj) !== 'Array') {
    if (typeof obj === 'function') {
      obj = eval(`(${obj.toString()})`)
    }
    return obj
  }

  let res = {}
  const origin = [obj]
  const copy = [res]
  const vistied = new Set([obj])

  while (origin.length) {
    const _obj = origin.shift()
    const copyObj = copy.shift()

    Object.keys(_obj).forEach(k => {
      const item = _obj[k]
      if (getType(item) === 'Object' || getType(item) === 'Array') {
        if (vistied.has(item)) {
          copyObj[k] = item
        } else {
          vistied.add(item)
          copyObj[k] = getType(item) === 'Object' ? {} : []
          origin.push(item)
          copy.push(copyObj[k])
        }
      } else if (typeof item === 'function') {
        copyObj[k] = eval(`(${item.toString()})`)
      } else {
        copyObj[k] = item
      }
    })
  }

  return res
}

缺陷:
没有实现对Symbol属性的处理,如果想实现的话可以用 Object.getOwnPropertySymbols()得到所有的Symbol属性,然后去遍历。

你可能感兴趣的:(对象深拷贝的两种实现方式(深度优先,广度优先))