一、什么是深拷贝和浅拷贝

  • 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是指向内存的地址 ,所以如果其中一个对象改变了这个引用类型的值,就会影响到另一个对象
  • 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

二、实现深拷贝的五种方式

1、递归调用

// 递归调用
const deepCopy = (obj) => {// 判断传入的值是否为一个对象if (obj === null && typeof obj !== "object") {return obj;}// 判断对象的类型 注意这里不考虑包装类对象if (Object.prototype.toString.call(obj) === "[object Date]") {return new Date(obj);}if (Object.prototype.toString.call(obj) === "[object RegExp]") {return new RegExp(obj);}if (Object.prototype.toString.call(obj) === "[object Undefined]") {return new Error(obj);}// 判断对象是类let newObj = Array.isArray(obj)  ? [] : {}for(let item in obj){if(typeof obj[item] === 'object') {newObj[item] = deepCopy(obj[item])}else {newObj[item] = obj[item]}}return newObj
};const foo = {name: '张三',info: {age: 24}
}
const newFoo = deepCopy(foo)
console.log(foo, newFoo)
foo.info.age = 25
console.log(foo, newFoo)

2、JSON.stringify + JSON.parse
:::info
更多关于JSON.stringigy的注意事项请看MDN
:::

// JSON.stringify
// 情况一: 对象内不存在undefined、symbol、function类型的属性时
// const foo = {//     name: '张三',
//     info: {//         age: 24
//     }
// }
// const newFoo = JSON.parse(JSON.stringify(foo))
// console.log(foo, newFoo) // { name: '张三', info: { age: 24 } } { name: '张三', info: { age: 24 } }
// foo.info.age = 25
// console.log(foo, newFoo) // { name: '张三', info: { age: 25 } } { name: '张三', info: { age: 24 } }// 情况二:当对象内存在undefined、symbol、function类型的属性时,在序列化过程中会被忽略。
// 当属性为NaN 和 Infinity 格式的数值及 null 都会被当做 nul
// const foo = {//   name: "张三",
//   age: undefined,
//   height: 183,
//   gender: Symbol("男"), //
//   say: () => {},
//   aa: NaN,
// };
// const newFoo = JSON.parse(JSON.stringify(foo));
// console.log(foo, newFoo); // {aa: NaN, age: undefined, gender: Symbol(男), height: 183, name: "张三"} { {name: '张三', height: 183, aa: null} }// JSON.stringify() 第二个参数为可选参数,可以是一个函数或者数组,
// 当是数组时表示需要被转化的属性列表,但undeinfed,symbol,function类型的属性依然会被忽略// const newFoo = JSON.parse(JSON.stringify(foo, ['name', 'age', 'gender', 'say', 'aa']));
// console.log(newFoo) // {name: '张三', aa: null}

3、lodash

const _ = require('lodash')
const foo = {name: '张三',info: {age: 24}
}
const newFoo = _.cloneDeep(foo);
foo.info.age = 25
console.log(foo, newFoo) // { name: '张三', info: { age: 25 } } { name: '张三', info: { age: 24 } }

4、Object.assgin

注意:只有当对象中没有嵌套对象时,才可以实现深拷贝
const foo = {name: '张三',age: 24
}
const newFoo = Object.assign({}, foo)
foo.age = 25
console.log(foo, newFoo) // {name: '张三', age: 25} {name: '张三', age: 24}// 对象中有内嵌的对象时
const foo = {name: '张三',info: {age: 24}
}
const newFoo = Object.assign({}, foo)
foo.info.age = 25
console.log(foo, newFoo) // { name: '张三', info: { age: 25 } } { name: '张三', info: { age: 25 } }

5、structuredClone

const foo = {name: '张三',info: {age: 24}
}
const newFoo = structuredClone(foo) //
foo.info.age = 25
console.log(foo, newFoo) // { name: '张三', info: { age: 25 } } { name: '张三', info: { age: 24 } }

该方法为Web最新的 API,存在兼容问题

深拷贝的五种实现方式相关推荐

  1. 前端百题斩【024】——我从浏览器控制台看到了五种存储方式

    写该系列文章的初衷是"让每位前端工程师掌握高频知识点,为工作助力".这是前端百题斩的第24斩,希望朋友们关注公众号"执鸢者",用知识武装自己的头脑. 打开浏览器 ...

  2. 浅拷贝的五种实现方式

    浅拷贝的五种实现方式 浅拷贝与深拷贝是一道经久不衰的面试题,今日先总结一下有哪些浅拷贝的方式,以及各自的优缺点 首先,看一下什么是浅拷贝 自己创建一个新的对象,来接受你要重新复制或引用的对象值.如果对 ...

  3. JavaScript中this的五种绑定方式详解

    1 this的五种绑定方式 1.1 默认绑定 默认绑定是指当函数调用时,没有为其指定对象上下文,此时会将该函数的this绑定到全局对象(window对象).自ES5有了严格模式之后,默认绑定方式又分为 ...

  4. 五种排序方式gif展示【python】

    简述 有五种排序方式. 文章目录 简述 排序 简单排序 冒泡排序 选择排序 归并排序 快速排序 排序 简单排序 import numpy as np import matplotlib.pyplot ...

  5. Silverlight C# 游戏开发:游戏循环体的五种设计方式

    我们在游戏设计和开发中,尤其是引擎开发中,逻辑循环是一个重要组成部分,循环决定了游戏的基础逻辑和运行方式,在不同的开发环境和语言下,对于循环的释义甚至相差甚远,那么我想和大家分享的是在Silverli ...

  6. 谈表达式树的缓存(7):五种缓存方式的总体分析及改进方案

    终于到了这个系列的最后一篇文章了,这个系列的文章本是许多话题的基础,却拖了那么长时间还没有完结.这篇文章主要讨论五种缓存方式各自的优劣,以及他们的性能关键在什么地方,如果要进行改进又有什么可选方案.在 ...

  7. Java防止Xss注入json_XSS的两种攻击方式及五种防御方式

    XSS介绍 跨站脚本攻击指的是自己的网站运行了别的网站里面的代码 攻击原理是原本需要接受数据但是一段脚本放置在了数据中: 该攻击方式能做什么? 获取页面数据 获取Cookies 劫持前端逻辑 发送请求 ...

  8. 后端技术:Java定时任务的五种创建方式

    Quartz表达式生成地址:http://cron.qqe2.com/ 支持生成定时任务表达式和反解析,使用Quartz表达式的定时任务如下 xxl-job springboot 的 @Schedul ...

  9. Jdbc连接mysql的五种连接方式

    一:五种连接方式 直接上码 package com.wyjedu.jdbc;import com.mysql.jdbc.Driver;import java.io.FileInputStream; i ...

最新文章

  1. 大整数减法c语言_C语言学习笔记(一)
  2. Quartz集成springMVC 的方案一
  3. 基于口令的密码PBE(Password Based Encryption)
  4. Junit单元测试遇到的initializationerror:method initializationerror not found
  5. 展望我的2022Flag
  6. c++ class struct同名_C/C++面向对象编程之封装
  7. Python+pandas读取Excel文件并统计演员参演电影数量
  8. 最近和一个35岁的朋友聊天,他最近在找工作
  9. 为什要学习烹饪?学习烹饪迫在眉睫
  10. Android 四大组件学习之ContentProvider三
  11. 用中位数代替平均数来衡量民生指标
  12. 理解 __doPostBack--2
  13. Windows 8 to Go
  14. hadoop jps 没有命令_hadoop:伪分布模式启动步骤分解
  15. vscode安装插件提示版本不匹配或版本过低
  16. 改写jtopo滚轮缩放代码
  17. 怎样在微信公众平台上传文件给别人下载
  18. Ubuntu安装播放器 或 Linux上比较好用强大、并且可以倍速播放的播放器SMplayer
  19. 广东未来科技AI立体数码相机:因细节而闪耀
  20. 门禁系统服务器需要什么要求,完备的门禁系统应该具有这些功能

热门文章

  1. 高手最爱的5大沟通技巧,管下属、谈客户都能用得上
  2. 2023美赛,还在等什么
  3. 29个习惯让你的拖延症一去不复返
  4. 各种遥感数据,地理信息数据共享网站
  5. 妖怪屋 服务器维护中,《阴阳师:妖怪屋》3月24日维护更新公告
  6. java读取文件特别慢_如何提高在Java中读取大文件的速度?
  7. 《了凡四训》读书总结
  8. echarts饼状曲线图,中间显示总数
  9. WCF 关闭默认调试客户端
  10. php curl exec 返回值,php curl_exec()函数 CURL获取返回值的方法