【JavaScript】手写深拷贝 2.0(更新 2022-07-15)
2022/7/15 14:20:25
本文主要是介绍【JavaScript】手写深拷贝 2.0(更新 2022-07-15),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
鄙人老版 js 深拷贝博客链接,当时写的存在很多不足...现在跟着方应杭老师复习了下,收获满满。
用 JSON
const b = JSON.parse(JSON.stringify(a))
缺点:
-
不支持 Date、RegExp(正则)、函数等数据;
-
不支持引用(即环状结构,类似 window.self = window)。
用递归
基础版
支持 Date、RegExp(正则)、函数等引用数据的拷贝。
const deepClone = (a) => { let res = undefined // 数据类型判断 if (a instanceof Object) { // 类 判断 if (a instanceof Function) { // 箭头函数判断 if (a.prototype) { // 普通函数 res = function (...args) { return a.call(this, ...args) } } else { // 箭头函数 res = (...args) => { return a.call(undefined, ...args) } } } else if (a instanceof Array) { res = [] } else if (a instanceof Date) { res = new Date(a - 0) // 日期格式 - 0 自动转换为时间戳 } else if (a instanceof RegExp) { res = new RegExp(a) } else { res = {} } // 递归 for (let k in a) { if (a.hasOwnProperty(k)) { res[k] = deepClone(a[k]) } } } else { res = a } return res }
测试结果:
完整版(支持引用自身的情况)
比如浏览器的 window.self = window,这个时候如果还用上面的拷贝就会导致无限递归导致栈溢出报错。
正确的做法是添加一个 map 来记录每次拷贝过的数据,如果出现重复的就不再进行拷贝和递归。(ps:为什么用 map?因为对象只能 key 值只能为字符串)
const deepClone = (a, cache) => { let res = undefined if(!cache){ cache = new Map() // 缓存不能全局,最好临时创建并递归传递 } if (a instanceof Object) { // 每次拷贝前判断前面是否已经拷贝过 // 如果出现 a.self = a 在这里就会返回 // 防止后续无限递归导致栈溢出 if (cache.get(a)) { return cache.get(a) } if (a instanceof Function) { if (a.prototype) { res = function (...args) { return a.call(this, ...args) } } else { res = (...args) => { return a.call(undefined, ...args) } } } else if (a instanceof Array) { res = [] } else if (a instanceof Date) { res = new Date(a - 0) } else if (a instanceof RegExp) { res = new RegExp(a) } else { res = {} } // 每次递归前将拷贝的值就存入 map cache.set(a, res) for (let k in a) { if (a.hasOwnProperty(k)) { // 通过参数传递缓存 map res[k] = deepClone(a[k], cache) } } } else { res = a } return res }
测试结果:
这篇关于【JavaScript】手写深拷贝 2.0(更新 2022-07-15)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-22[开源]10.3K+ Star!轻量强大的开源运维平台,超赞!
- 2024-11-21Flutter基础教程:新手入门指南
- 2024-11-21Flutter跨平台教程:新手入门详解
- 2024-11-21Flutter跨平台教程:新手入门与实践指南
- 2024-11-21Flutter列表组件教程:初学者指南
- 2024-11-21Flutter列表组件教程:新手入门指南
- 2024-11-21Flutter入门教程:初学者必看指南
- 2024-11-21Flutter入门教程:从零开始的Flutter开发指南
- 2024-11-21Flutter升级教程:新手必读的升级指南
- 2024-11-21Flutter升级教程:轻松掌握Flutter版本更新