网站开发项目描述网络暴力事件
前情提要
最近在调uni-app时,经常遇到需要深拷贝对象的情况,今天正好有空,给大家博主用到的深拷贝的方法。
最常用的序列化方法
这个是博主最常用的方法,也是个人认为最简洁方便的的,唯一的确定就是部分特殊类型会拷贝失效,总结如下
优点: 简单快捷,兼容性好
缺点: 无法处理 undefined、function、Symbol 类型、Date 对象(转为 ISO 字符串)、正则表达式(转为空对象)
<html>
<style></style>
<body></body>
<script>const obj = { a:undefined, b:{b1:1}, c:'测试', d:new Date(), f:function(){} };const newObj = JSON.parse(JSON.stringify(obj));// 输出 {b:{b1: 1}, c:"测试", d:"2025-04-11T09:16:12.039Z"}console.log(newObj)
</script>
</html>
原生方法structuredClone
该方法是HTML5新推出,相比序列化方法,支持了更多数据类型,且更简便了,但是兼容性较差,总结如下
优点: 浏览器原生方法,支持更多数据类型(undefined、Date 对象等)
缺点: 不支持函数、DOM 节点等,且对兼容性有要求,需较新浏览器
<html>
<style></style>
<body></body>
<script>const obj = { a:undefined, b:{b1:1}, c:'测试', d:new Date() };const newObj = structuredClone(obj);// 输出 {a:undefined, b:{b1: 1}, c:"测试", d: Fri Apr 11 2025 17:19:31 GMT+0800 (中国标准时间)}console.log(newObj)
</script>
</html>
MessageChannel 异步拷贝
该方法是通过信道通信间的传输,来实现对象的深度拷贝,能处理大部分数据类型,唯一的缺点就是需要异步操作
优点: 能处理除了函数外的大部分数据类型
缺点: 需要异步操作,会增加代码的复杂性
<html>
<style></style>
<body></body>
<script>const obj = { a:undefined, b:{b1:1}, c:'测试', d:new Date() };function deepClone(obj) {return new Promise(resolve => {const { port1, port2 } = new MessageChannel()port2.onmessage = ev => resolve(ev.data)port1.postMessage(obj)})}deepClone(obj).then(newObj=>{// 输出 {a:undefined, b:{b1: 1}, c:"测试", d: Fri Apr 11 2025 17:19:31 GMT+0800 (中国标准时间)}console.log(newObj)})
</script>
</html>
自定义方法
最后一种就是我们自己写的方法了,具体总结如下
优点: 可自定义处理特殊类型
缺点: 需要手动处理各种数据类型(Date/RegExp/Map/Set等),性能较差(大数据量时)
<html>
<style></style>
<body></body>
<script>const obj = { a:undefined, b:{b1:1}, c:'测试', d:new Date() };function deepClone(obj, map = new WeakMap()) {if (obj === null || typeof obj !== 'object') return objif (map.has(obj)) return map.get(obj)let clone = Array.isArray(obj) ? [] : {}map.set(obj, clone)for (let key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key], map)}}return clone}const newObj = deepClone(obj);// 输出 {a:undefined, b:{b1: 1}, c:"测试", d: Fri Apr 11 2025 17:19:31 GMT+0800 (中国标准时间)}console.log(newObj)
</script>
</html>
总结
博主能力有限,基本就只能总结这四种了,大家也可以选择第三方库去实现对象之间的深拷贝,或者有什么其他方法都可评论讨论。