手写系列之深度拷贝 - 图1


    本文讨论的是如何进行深度拷贝,大致的原理其实看注释就能看明白

    1. const { getTypes } = require('where-type')
    2. // 这些对象值得深度克隆
    3. const OBJECT_TYPES = [
    4. {},
    5. [],
    6. new Map(),
    7. new Set(),
    8. new Error(),
    9. new Date(),
    10. /^$/
    11. ].map((item) => getTypes(item))
    12. const CONSTRUCT_TYPE = [new Error(), new Date()].map((item) => getTypes(item))
    13. const SYMBOL_TYPE = getTypes(Symbol('1'))
    14. const REGEXP_TYPE = getTypes(/^$/)
    15. const MAP_TYPE = getTypes(new Map())
    16. const SET_TYPE = getTypes(new Set())
    17. /**
    18. * @author lihh
    19. * @description 进行深度克隆
    20. * @param target 克隆源
    21. */
    22. function deepCopy(target, weakMap = new WeakMap()) {
    23. // 除了上述的类型 都是按基本数据类型计算
    24. const type = getTypes(target)
    25. if (!OBJECT_TYPES.includes(type)) return target
    26. // 避免嵌套迭代,使用缓存
    27. if (weakMap.has(target)) return weakMap.get(target)
    28. // 针对error,date做处理
    29. if (CONSTRUCT_TYPE.includes(type)) return new target.constructor(target)
    30. const copyTarget = new target.constructor()
    31. weakMap.set(target, copyTarget)
    32. // 针对symbol做处理
    33. if (SYMBOL_TYPE === type) return Object(Symbol.prototype.valueOf.call(target))
    34. // 针对正则表达式
    35. if (REGEXP_TYPE === type) {
    36. const flags = /\w*$/
    37. const result = new target.constructor(target.source, flags.exec(target))
    38. result.lastIndex = target.lastIndex
    39. return result
    40. }
    41. // 针对set处理
    42. if (SET_TYPE === type) {
    43. target.forEach((value) => {
    44. copyTarget.add(deepCopy(value, weakMap))
    45. })
    46. return copyTarget
    47. }
    48. // 针对map处理
    49. if (MAP_TYPE === type) {
    50. target.forEach((value, key) => {
    51. copyTarget.set(key, deepCopy(value, weakMap))
    52. })
    53. return copyTarget
    54. }
    55. for (const item in target) {
    56. // 判断是否是自身属性 因为in会迭代原型链
    57. if (target.hasOwnProperty(item)) {
    58. copyTarget[item] = deepCopy(target[item], weakMap)
    59. }
    60. }
    61. return copyTarget
    62. }
    63. module.exports = deepCopy