js深拷贝的四种境界

1,099 阅读1分钟

看了一些博客和代码后,总结一下:

第一层境界:JSON.parse(JSON.stringify)

巧妙利用JSON, 但是也受限于json,只支持json内的数据类型:Boolean,Null,Number,String,Object;Object只是普通的字面量对象以及嵌套字面量对象,Boolean,Null,Number,String的Object,不包括Function,RegExp,Date等等

第二层境界:30-seconds-of-code/deepClone

先来个有意思的表达式: Array.from(Object.assign({length: 2}, [1, 2])) 巧妙利用 Object.assign + Array.from,凡是继承于Object的Function, Date, Error, RegExp, Symbol, Map, WeakMap都可以实现深clone,以及(类)数组: arguments,Array,Set,WeakSet,ES7+的ArrayBuffer,DataView,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array, Uint8Array, Uint8clampedArray, Uint16Array, Uint32Array

function deepClone (obj) {
  const clone = Object.assign({}, obj)
  Object.keys(clone).forEach(
    key => (clone[key] = typeof clone[key] === 'object' ? deepClone(obj[key]) : obj[key])
  )
  return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone
}

第三层境界:Lodash-deepClone

支持的数据类型是在第二层境界里面提及的一致,但是实现方式不一样,Lodash针对细分的不同数据类型会有不同的clone逻辑,分在不同的子文件,比如:

lodash-cloneDeep

function cloneRegExp (regexp) {
  const result = new regexp.constructor(regexp.source, reFlags.exec(regexp))
  result.lastIndex = regexp.lastIndex
  return result
}

export default cloneRegExp

第四层境界: 考虑循环引用

在第二种,第三种的境界上考虑递归爆栈,循环引用,引用丢失的情况如何处理,掘金上的这一篇文章讲的我头大,此乃第四种境界

关于JavaScript-clone就讲这么多了,最为简便的方法在于第二种,也是应用最广的,特殊场景考虑第四种。