just-clone函数学习

15 阅读1分钟

clone是js中老生常谈的问题了,just这个库,实现了一个简易版的克隆。
根据我在真实场景下的经验,一般的深克隆也大多都是考虑到数组和对象就行了,并且像循环引用这种根本不会出现,所以我觉得在一般场景下是够用的了。
然后也确实想去通过观看别人优秀的代码,理解并自己能够写出来,来提升自己。

当然我们这里说的都是深克隆

 function clone(obj) {
  const valueType = Object.prototype.toString.call(obj).slice(8, -1)

  // 这个赋值是为了克隆基础类型数据
  let result = obj

  // 克隆Set
  if (valueType === 'Set') {
    return new Set([...obj].map(value => clone(value)))
  }

  // 克隆Map
  if (valueType === 'Map') {
    return new Map([...obj].map(([k, v]) => [clone(k), clone(v)]))
  }

  // 克隆Date
  if (valueType === 'Date') {
    return new Date(obj.getTime())
  }


  // 克隆RegExp
  if (valueType === 'RegExp') {
    return new RegExp(obj.source, getRegFlags(obj))
  }

  // 克隆数组或者对象
  if (valueType === 'Array' || valueType === 'Object') {
    result = Array.isArray(obj) ? [] : {}
    for (let k in obj) {
      result[k] = clone(obj[k])
    }
  }

  return result
}

function getRegFlags(reg) {
  if (reg.flags) {
    return reg.flags
  }

  const flags = []

  reg.indices && flags.push('d')
  reg.global && flags.push('g')
  reg.ignoreCase && flags.push('i')
  reg.multiline && flags.push('m')
  reg.dotAll && flags.push('s')
  reg.unicode && flags.push('u')
  reg.unicodeSets && flags('v')
  reg.sticky && flags.push('y')

  return flags.join('')
}

主要的思路就是通过Object原型上的toString方法,获取到当前值的类型,根据不同类型去做不同的处理 如果不是引用类型,那就直接返回