Javascript 中常见的三种对象处理的方式
    赋值、浅拷贝、深拷贝

    深拷贝和浅拷贝
    image.png
    浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

    赋值和浅拷贝
    **
    赋值:
    当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

    浅拷贝:
    浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型,拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

    类型 是否指向同一对象 第一层为基本数据类型 第一层为引用数据类型
    赋值 改变会导致数据改变 改变会导致数据改变
    浅拷贝 改变不会导致数据改变 改变会导致数据改变
    深拷贝 改变不会导致数据改变 改变不会导致数据改变

    简单的浅拷贝

    1. Object.assign({},obj) 浅拷贝object
    2. obj1={...obj2} 通过spread展开运算符浅拷贝obj2
    3. Object.fromEntries(Object.entries(obj)) 通过生成迭代器再通过迭代器生成对象
    4. Object.create({},Object.getOwnPropertyDescriptors(obj)) 浅拷贝obj
    5. Object.defineProperties({},Object.getOwnPropertyDescriptors(obj)) 浅拷贝obj

    深拷贝

    1. //简单版深拷贝,只能拷贝基本原始类型和普通对象与数组,无法拷贝循环引用
    2. function simpleDeepClone(a) {
    3. const b=Array.isArray(a) ? [] : {}
    4. for (const key of Object.keys(a)) {
    5. const type = typeof a[key]
    6. if (type !== 'object' || a[key] === null) {
    7. b[key] = a[key]
    8. } else {
    9. b[key] = simpleDeepClone(a[key])
    10. }
    11. }
    12. return b
    13. }
    14. //精简版深拷贝只能拷贝基本原始类型和普通对象与数组,可以拷贝循环引用
    15. function deepClone(a, weakMap = new WeakMap()) {
    16. if (typeof a !== 'object' || a === null) return a
    17. if (s = weakMap.get(a)) return s
    18. const b = Array.isArray(a) ? [] : {}
    19. weakMap.set(a, b)
    20. for (const key of Object.keys(a)) b[key] = clone(a[key], weakMap)
    21. return b
    22. }
    23. //js原生深拷贝,无法拷贝Symbol、null、循环引用
    24. function JSdeepClone(data) {
    25. if (!data || !(data instanceof Object) || (typeof data == "function")) {
    26. return data || undefined;
    27. }
    28. const constructor = data.constructor;
    29. const result = new constructor();
    30. for (const key in data) {
    31. if (data.hasOwnProperty(key)) {
    32. result[key] = deepClone(data[key]);
    33. }
    34. }
    35. return result;
    36. }
    37. //深拷贝具体版,非完全,但大部分都可以
    38. function deepClonePlus(a, weakMap = new WeakMap()) {
    39. const type = typeof a
    40. if (a === null || type !== 'object') return a
    41. if (s = weakMap.get(a)) return s
    42. const allKeys = Reflect.ownKeys(a)
    43. const newObj = Array.isArray(a) ? [] : {}
    44. weakMap.set(a, newObj)
    45. for (const key of allKeys) {
    46. const value = a[key]
    47. const T = typeof value
    48. if (value === null || T !== 'object') {
    49. newObj[key] = value
    50. continue
    51. }
    52. const objT = Object.prototype.toString.call(value)
    53. if (objT === '[object Object]' || objT === '[object Array]') {
    54. newObj[key] = deepClonePlus(value, weakMap)
    55. continue
    56. }
    57. if (objT === '[object Set]' || objT === '[object Map]') {
    58. if (objT === '[object Set]') {
    59. newObj[key] = new Set()
    60. value.forEach(v => newObj[key].add(deepClonePlus(v, weakMap)))
    61. } else {
    62. newObj[key] = new Map()
    63. value.forEach((v, i) => newObj[key].set(i, deepClonePlus(v, weakMap)))
    64. }
    65. continue
    66. }
    67. if (objT === '[object Symbol]') {
    68. newObj[key] = Object(Symbol.prototype.valueOf.call(value))
    69. continue
    70. }
    71. newObj[key] = new a[key].constructor(value)
    72. }
    73. return newObj
    74. }

    —————————————————————————————————————————
    引用:
    部分引用并参考了原文 : https://juejin.im/post/6844904136161361933#heading-13
    部分引用并参考了原文 : https://segmentfault.com/a/1190000018874254