1. // 递归
    2. function dfsCloneDeep(source, hash = new WeakMap()) {
    3. if (!typeof sorce === 'object') return source; // 非对象返回自身
    4. if (hash.has(source)) return hash.get(source); // 查哈希表,如果以拷贝,则直接返回值,解决循环引用
    5. let target = Array.isArray(source) ? [] : {}; // 区分数组和对象
    6. hash.set(source, target); // 哈希表设值,哈希表存储已拷贝过的对象
    7. let symKeys = Object.getOwnPropertySymbols(source); // 解决拷贝symbol
    8. if (symKeys.length) {
    9. symKeys.forEach(symKey => {
    10. if (typeof source[symKey] === 'object' && source[symKey] !== null) {
    11. target[symKey] = dfsCloneDeep(source[symKey], hash);
    12. } else {
    13. target[symKey] = source[symKey];
    14. }
    15. });
    16. }
    17. for(let key in source) {
    18. if (Object.prototype.hasOwnProperty.call(source, key)) {
    19. if (typeof source[key] === 'object' && source[key] !== null) {
    20. target[key] = dfsCloneDeep(source[key], hash); // 注意这里传入hash
    21. } else {
    22. target[key] = source[key];
    23. }
    24. }
    25. }
    26. return target;
    27. }
    28. // 队列
    29. function bfsCloneDeep(obj) {
    30. let root = Array.isArray(obj) ? [] : {};
    31. let nodeList = [{
    32. parent: root,
    33. key: undefined,
    34. data: obj,
    35. }];
    36. while (nodeList.length) {
    37. let node = nodeList.pop(),
    38. parent = node.parent,
    39. key = node.key,
    40. data = node.data;
    41. let result = parent;
    42. if (typeof key !== 'undefined') { // 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
    43. result = parent[key] = Array.isArray(data) ? [] : {};
    44. }
    45. let symKeys = Object.getOwnPropertySymbols(data); // 解决拷贝symbol
    46. if (symKeys.length) {
    47. symKeys.forEach(symKey => {
    48. if (typeof data[symKey] === 'object' && data[symKey] !== null) {
    49. nodeList.push({
    50. parent: result,
    51. key: symKeys,
    52. data: data[symKey],
    53. });
    54. } else {
    55. result[symKey] = data[symKey];
    56. }
    57. });
    58. }
    59. for (let key in data) {
    60. if (data.hasOwnProperty(key)) {
    61. if (typeof data[key] === 'object') {
    62. nodeList.push({
    63. parent: result,
    64. key,
    65. data: data[key],
    66. });
    67. } else {
    68. result[key] = data[key];
    69. }
    70. }
    71. }
    72. }
    73. return root;
    74. };
    75. let obj = {colors: ['blue', 'red'],width: 200, height: 300};
    76. let l = Symbol('length');
    77. obj[l] = 400 ;
    78. let obj1 = bfsCloneDeep(obj)
    79. // {colors: ['blue', 'red'], width: 200, height: 300, Symbol(length): 400}
    80. let obj2 = dfsCloneDeep(obj)
    81. // {colors: ['blue', 'red'], width: 200, height: 300, Symbol(length): 400}