Directly on the bar code, and then some understanding of things that are written in the code above
1 // whether the test object is a function of 2 function isObject (X) { . 3 return Object.prototype.toString.call (X) === '[Object Object]' . 4 } . 5 . 6 // in the array list, to find out whether is subject to the same address 7 // there, the object returns, otherwise return null . 8 function Find (ARR, Item) { . 9 for (the let I = 0; I <arr.length; I ++ ) { 10 IF (ARR [I ] .source === Item) { . 11 return ARR [I]; 12 is } 13 is } 14 15 return null ; 16 } . 17 18 is // This is a simple clone 19 // there are many problems, 20 // not check the parameters 21 // not to make the explosion process stack 22 @ readily endless loop 23 is function clone (X) { 24 the let Data = {} 25 the let RES = Data; 26 is 27 for ( var K in X) { 28 IF (x.hasOwnProperty (K)) { 29 RES [K] = clone (X [K]) 30 } The else { 31 is RES [K] = X [K] 32 } 33 is } 34 is 35 return RES 36 } 37 [ 38 is // the JSON.parse and JSON.stringify package 39 // there recursive 40 @ and has a loop detection ( anti-dead cycle) 41 is function cloneJson (X) { 42 is return the JSON.parse (the JSON.stringify (X)) 43 is } 44 is 45 // here made explosion process stack 46 // only for objects made clone 47 // but did not do as well as anti endless loop 48 function cloneLoop (X) { 49 IF (isObject (X)!) Return X; 50 const the root = {} 51 is 52 is const loopList = [ 53 is { 54 is parent: the root, 55 Key : undefined, 56 is Data: X 57 is } 58 ] 59 60 the while (loopList.length) { 61 is const Node = loopList.pop (); 62 const parent = node.parent; 63 const key = node.key; 64 const data = node.data; 65 66 let temp = parent; 67 // 如果key为undedined 68 if (typeof key !== undefined) { 69 temp = parent[key] = {} 70 } 71 72 for (var k in data) { 73 if (data.hasOwnProperty(k)) { 74 if (isObject(data[k])) { 75 loopList.push({ 76 parent: temp, 77 key: k, 78 data: data[k] 79 }) 80 } 81 } else { 82 temp[k] = data[k] 83 } 84 } 85 } 86 87 return root 88 } 89 90 // further optimized 91 // former method, the object in the same reference, the reference relationship can cut 92 // here will not, and can have the role of preventing the endless loop 93 function cloneForce (X) { 94 // 1. prevent the blast stack 95 @ 2. The reference solution lost 96 IF (isObject (X)!) return X; 97 98 // ============= 99 const uniqueList = [] ; // used to weight 100 @ ============= 101 const the root = {}; 102 const = loopList [{ 103 parent: root, 104 key: undefined, 105 data: x, 106 }] 107 108 while (loopList.length) { 109 const node = loopList.pop(); 110 const parent = node.parent; 111 const key = node.key; 112 const data = node.data; 113 114 let res = parent; 115 116 if (typeof key !== 'undefined') { 117 res = parent[key] = {} 118 } 119 120 let uniqueData = find(uniqueList, data) 121 if (uniqueData) { 122 parent[key] = uniqueData.target; 123 break; 124 } 125 126 uniqueList.push({ 127 source: data, 128 target: res 129 }) 130 131 for (var k in data) { 132 if (data.hasOwnProperty(k)) { 133 if (isObject(data[k])) { 134 loopList.push({ 135 parent: res, 136 key: k, 137 data: data[k] 138 }) 139 } else { 140 res[k] = data[k] 141 } 142 } 143 } 144 145 return the root; 146 } 147 } 148 149 // used to quickly create an object 150 function createData (Deep, the breadth) { 151 // Deep Depth 152 // the breadth breadth 153 the let Data = {} 154 the let TEMP = Data ; 155 156 for ( var I = 0; I <Deep; I ++ ) { 157 TEMP TEMP = [ 'Data'] = {} 158 for (var j = 0; j < breadth; j++) { 159 temp[j] = j 160 } 161 } 162 163 return data 164 } 165 166 // 用来测试性能 167 function test(fn, time) { 168 let count = 0; 169 let startTime = new Date().getTime(); 170 while(new Date().getTime - startTime < time) { 171 fn(); 172 count++; 173 } 174 return count; 175 } 176 177 test(function () { 178 cloneForce(createData(10000)) 179 }, 2000)
References:
1. https://segmentfault.com/a/1190000016672263
2.https://juejin.im/post/5e34d19de51d4558864b1d1f#heading-36