深克隆记录

直接上代码吧,然后将一些理解的东西写在代码上面

  1 // 检验是否是对象的函数
  2         function isObject(x) {
  3             return Object.prototype.toString.call(x) === '[object Object]'
  4         }
  5 
  6         // 在数组列表中,查找是否是相同地址的对象,
  7         // 有,返回该对象,否则返回null
  8         function find(arr, item) {
  9             for(let i = 0; i < arr.length; i++) {
 10                 if (arr[i].source === item) {
 11                     return arr[i];
 12                 }
 13             }
 14 
 15             return null;
 16         }
 17 
 18         // 这是个简单的克隆,
 19         // 有很多的问题,
 20         // 没对参数进行校验
 21         // 没对爆栈做处理
 22         // 容易陷入死循环
 23         function clone(x) {
 24             let data = {}
 25             let res = data;
 26 
 27             for(var k in x) {
 28                 if (x.hasOwnProperty(k)) {
 29                     res[k] = clone(x[k])
 30                 } else {
 31                     res[k] = x[k]
 32                 }
 33             }
 34 
 35             return res
 36         }
 37 
 38         // JSON.parse和JSON.stringify的封装
 39         // 里面有递归
 40         // 并且有循环检测(防死循环)
 41         function cloneJson(x) {
 42             return JSON.parse(JSON.stringify(x))
 43         }
 44 
 45         // 这里做了防爆栈处理
 46         // 只对对象做了克隆
 47         // 但是还有防死循环没做
 48         function cloneLoop(x) {
 49             if(!isObject(x)) return x;
 50             const root = {}
 51 
 52             const loopList = [
 53                 {
 54                     parent: root,
 55                     key: undefined,
 56                     data: x
 57                 }
 58             ]
 59 
 60             while(loopList.length) {
 61                 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         // 进一步优化
 91         // 前一种方法,对象里有相同的引用,会切断引用关系
 92         // 这里不会,并且能有防死循环的作用
 93         function cloneForce(x) {
 94             // 1.防止爆栈
 95             // 2.解决引用丢失
 96             if(!isObject(x)) return x;
 97 
 98             // =============
 99             const uniqueList = []; // 用来去重
100             // =============
101             const 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 root;
146             }
147         }
148     
149         // 用来快速创建对象
150         function createData(deep, breadth) {
151             // deep 深度
152             // breadth 广度
153             let data = {}
154             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)

参考文献:
 1. https://segmentfault.com/a/1190000016672263

 2.https://juejin.im/post/5e34d19de51d4558864b1d1f#heading-36

猜你喜欢

转载自www.cnblogs.com/junjunjiayuan/p/12305686.html