这次让面试官非常满意:手撕深拷贝[15行]



这次让面试官非常满意:手撕深拷贝

-------------人工分割线-------------

浅拷贝这里不做介绍了,深拷贝的实现要点,除了一定要深!还要能兼容各种类型,如函数,正则、Date等等。
其实日常业务开发中,Json.parse(Json.stringfy(obj))已经能够解决90%左右的克隆需求。还有Object.assign() Object.create()都能满足一定的克隆需求。

但上班拧螺丝,面试造航母的精神不容小觑!本着专研精神去看待怎么才能写个牛逼、各种场合都能通用的克隆方式?我做了不少功课。

在思考如何实现深拷贝之前,首先得弄明白:

如何遍历对象?点这可以传送

如何判断数据类型?点这可以传送

如何创建对象?【由于懒没写】

如何克隆函数,正则、Date对象?

如何解决循环引用问题?

实现思路:

使用递归实现嵌套对象的遍历

增加WeakMap来缓存已经创建的克隆对象解决循环引用问题

区分不同数据类型的处理方式,增加通用类型集合来存储通用类型,方便日后拓展

直接上代码:

待克隆对象

let obj = { newDate: new Date('2020-10-11 12:00:01'), null: null, string: 'string', num: 23, nan: NaN, func: function () {console.log('function')}, arr: [1,2,3], reg: /ABC\-001/, regObj: new RegExp(/ABC/), object: { c: { a: 1 } }, }; obj.loop = obj; // 循环引用 let sup = { name: 'super', show: function () { console.log('show') } } let objectSup = { objectSupName: 'objectSupName', objectSupShow: function () { console.log('objectSupShow') } } Object.setPrototypeOf(obj, sup); // 根对象设置原型对象 Object.setPrototypeOf(obj.object, objectSup); // 子对象设置原型对象

核心代码

// 使用WeakMap是便于回收 function deepClone(obj, cacheCurr = new WeakMap()) { // 如果该对象已经创建好,则从缓存中获取直接返回 if (cacheCurr.has(obj)) return cacheCurr.get(obj); // 通用的类型集合,方便后面统一处理:new obj.constructor(obj),所以该集合一定是要能够这样创建的才能放进来 const types = ['RegExp', 'Date', 'Set', 'Map', 'WeakMap', 'WeakSet']; // 获取当前对象类型 let objDataType = Object.prototype.toString.call(obj).slice(8, -1); // 对比当前类型是否在通用类型中,在则统一处理克隆。【较通用的处理方式】 if(types.includes(objDataType)) return new obj.constructor(obj); // 创建克隆对象 let cloneObj = objDataType === 'Array' ? [] : {}; // 继承原型 if(obj) Object.setPrototypeOf(cloneObj,Object.getPrototypeOf(obj)); // 普通引用类型及非引用类型克隆,Reflect.ownKeys能够获取自身所有属性【非枚举也可】 for(let key of Reflect.ownKeys(obj)) { let value = obj[key]; let valueType = Object.prototype.toString.call(value).slice(8, -1); // 引用类型处理 if(valueType === 'Object' || valueType === 'Array' || types.includes(valueType)) { // 对引用类型进行递归进入当前级的下一级进行遍历 cloneObj[key] = deepClone(value, cacheCurr); // 记录已创建引用 cacheCurr.set(obj, cloneObj); } else { // 非引用类型处理 cloneObj[key] = value; } } return cloneObj; }

代码注释感觉都写的很清楚了。写完这篇文章就可以安心的来一把无限火力了。

测试过挺多数据结构的都完美通过。如果有发现问题的同学帮忙指出来。感激不尽

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydfdx.html