深拷贝的五种实现方式
一、什么是深拷贝和浅拷贝
- 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是指向内存的地址 ,所以如果其中一个对象改变了这个引用类型的值,就会影响到另一个对象。
- 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
二、实现深拷贝的五种方式
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,存在兼容问题
深拷贝的五种实现方式相关推荐
- 前端百题斩【024】——我从浏览器控制台看到了五种存储方式
写该系列文章的初衷是"让每位前端工程师掌握高频知识点,为工作助力".这是前端百题斩的第24斩,希望朋友们关注公众号"执鸢者",用知识武装自己的头脑. 打开浏览器 ...
- 浅拷贝的五种实现方式
浅拷贝的五种实现方式 浅拷贝与深拷贝是一道经久不衰的面试题,今日先总结一下有哪些浅拷贝的方式,以及各自的优缺点 首先,看一下什么是浅拷贝 自己创建一个新的对象,来接受你要重新复制或引用的对象值.如果对 ...
- JavaScript中this的五种绑定方式详解
1 this的五种绑定方式 1.1 默认绑定 默认绑定是指当函数调用时,没有为其指定对象上下文,此时会将该函数的this绑定到全局对象(window对象).自ES5有了严格模式之后,默认绑定方式又分为 ...
- 五种排序方式gif展示【python】
简述 有五种排序方式. 文章目录 简述 排序 简单排序 冒泡排序 选择排序 归并排序 快速排序 排序 简单排序 import numpy as np import matplotlib.pyplot ...
- Silverlight C# 游戏开发:游戏循环体的五种设计方式
我们在游戏设计和开发中,尤其是引擎开发中,逻辑循环是一个重要组成部分,循环决定了游戏的基础逻辑和运行方式,在不同的开发环境和语言下,对于循环的释义甚至相差甚远,那么我想和大家分享的是在Silverli ...
- 谈表达式树的缓存(7):五种缓存方式的总体分析及改进方案
终于到了这个系列的最后一篇文章了,这个系列的文章本是许多话题的基础,却拖了那么长时间还没有完结.这篇文章主要讨论五种缓存方式各自的优劣,以及他们的性能关键在什么地方,如果要进行改进又有什么可选方案.在 ...
- Java防止Xss注入json_XSS的两种攻击方式及五种防御方式
XSS介绍 跨站脚本攻击指的是自己的网站运行了别的网站里面的代码 攻击原理是原本需要接受数据但是一段脚本放置在了数据中: 该攻击方式能做什么? 获取页面数据 获取Cookies 劫持前端逻辑 发送请求 ...
- 后端技术:Java定时任务的五种创建方式
Quartz表达式生成地址:http://cron.qqe2.com/ 支持生成定时任务表达式和反解析,使用Quartz表达式的定时任务如下 xxl-job springboot 的 @Schedul ...
- Jdbc连接mysql的五种连接方式
一:五种连接方式 直接上码 package com.wyjedu.jdbc;import com.mysql.jdbc.Driver;import java.io.FileInputStream; i ...
最新文章
- 大整数减法c语言_C语言学习笔记(一)
- Quartz集成springMVC 的方案一
- 基于口令的密码PBE(Password Based Encryption)
- Junit单元测试遇到的initializationerror:method initializationerror not found
- 展望我的2022Flag
- c++ class struct同名_C/C++面向对象编程之封装
- Python+pandas读取Excel文件并统计演员参演电影数量
- 最近和一个35岁的朋友聊天,他最近在找工作
- 为什要学习烹饪?学习烹饪迫在眉睫
- Android 四大组件学习之ContentProvider三
- 用中位数代替平均数来衡量民生指标
- 理解 __doPostBack--2
- Windows 8 to Go
- hadoop jps 没有命令_hadoop:伪分布模式启动步骤分解
- vscode安装插件提示版本不匹配或版本过低
- 改写jtopo滚轮缩放代码
- 怎样在微信公众平台上传文件给别人下载
- Ubuntu安装播放器 或 Linux上比较好用强大、并且可以倍速播放的播放器SMplayer
- 广东未来科技AI立体数码相机:因细节而闪耀
- 门禁系统服务器需要什么要求,完备的门禁系统应该具有这些功能