deepClone

265 阅读1分钟

deep clone 需要考虑引用类型(object, function),primitve 类型和数组,Map, Set,如果obj是一个object,那么需要copy它的每一个属性。如果obj是一个数组,那么需要拷贝它的每一个数组元素,如果是Map需要新建一个Map,如果是Set需要新建一个Set。因此需要Object.keys(), Object.entries(),Array.prototype.map, Map.prototype.set, Set.prototype.add 等方法。

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

function deepClone(obj) {
  let target
  if (null === obj) {
    return null
  }
  const type = getType(obj)
  if (type === 'map') {
    target = new Map()
    for (let [key, value] of obj) {
      target.set(key, value)
    }
  } else if (type === 'set') {
    target = new Set()
    for (let item of obj) {
      target.add(item)
    } 
  } else if (type === 'array') {
    target = obj.map(item => {
      return deepClone(item)
    })
  } else {
    target = {}
    Object.entries(obj).forEach(([key, value]) => {
      target[key] = typeof value === 'object' ? deepClone(value) : value
    })
  }
  return target
}

const a1 = Symbol('foo')
const a2 = new Set([1, 2, 3])
const a3 = new Map([[1, 'one'], [2, 'two']])

const a = [{ foo: a2, foo2: a3, foo3: a1, obj: { a: 1, b: 2 }, c: [{d: 4}] }];
const b = deepClone(a);
console.log('b', b[0].foo, b[0].foo2, b[0].foo3)