Skip to main content

深拷贝

CREATE: 2022-03-11 22:14:09

题目:深拷贝 ( 中等😄 )

请利用Ts | Js,实现深拷贝函数

分析

深拷贝实现程度不一,实现方式也有很多种

实现程度

  • 能够处理对象
  • 能够处理对象和数组
  • 能够解决对象循环引用问题

方式:

  • JSON方式

    • 只适用于拷贝基础类型,例如:string、boolean、null、number、undefined
    • 无法处理引用数据类型,例如:function, RegExp, function等
    • 应用场景:拷贝接口数据
  • 递归

    一层一层判断元素类型,并进行拷贝

注意

生产中,建议使用 lodashcloneDeep

题解

JSON方式

function cloneDeep1(value) {
return JSON.parse(JSON.stringify(value))
}

递归

能够递归拷贝数组和对象以及绝大多数引用类型,但实现并不完整,无法拷贝函数,没有处理循环引用问题

部分写法参考lodash库的cloneDeep

const arrayTag = '[object Array]'
const boolTag = '[object Boolean]'
const dateTag = '[object Date]'
const errorTag = '[object Error]'
const mapTag = '[object Map]'
const numberTag = '[object Number]'
const objectTag = '[object Object]'
const regexpTag = '[object RegExp]'
const setTag = '[object Set]'
const stringTag = '[object String]'
const symbolTag = '[object Symbol]'
const weakMapTag = '[object WeakMap]'

function getTag(value) {
if (value == null) {
return value === undefined ? '[object Undefined]' : '[object Null]'
}
return Object.prototype.toString.call(value)
}

function isObject(value) {
const type = typeof value
return value != null && (type === 'object' || type === 'function')
}

function isArray(value) {
return Array.isArray(value)
}

function cloneDeep2(value) {
// regard null as not object
if (!isObject(value)) {
return value
}

if (isArray(value)) {
return value.map((x) => {
return cloneDeep2(x)
})
} else {
const tag = getTag(value)

if (tag == regexpTag) {
return new RegExp(value)
} else if (tag == dateTag) {
return new Date(value)
} else if (tag == errorTag) {
return new Error(value)
} else if (tag == mapTag) {
const newMap = new Map()
value.forEach((subValue, key) => {
newMap.set(key, cloneDeep2(subValue))
})

return newMap
} else if (tag == setTag) {
const newSet = new Set()
value.forEach((subValue) => {
newSet.add(cloneDeep2(subValue))
})

return newSet
} else {
return Object.keys(value).reduce((memo, key) => {
memo[key] = cloneDeep2(value[key])

return memo
}, {})
}
}
}