JavaScript之深浅拷贝

JavaScript之深浅拷贝上篇博客中简单介绍了 JS 中的引用类型 本篇博客就简单介绍下 JS 的深浅拷贝 以后有时间再对深浅拷贝做个扩展 原始类型是保存在栈内存中的 对于它们的复制可以理解为 真实 复制 即重新开辟栈内存并将原来的值 copy 一份放进去 那么修改 copy 的那个值并不会影响原始值 因为它们是独立的 先看看原始类型和引用类型的存储方式 图片摘自 https www cnbl

        上篇博客中简单介绍了JS中的引用类型,本篇博客就简单介绍下JS的深浅拷贝,以后有时间再对深浅拷贝做个扩展。原始类型是保存在栈内存中的,对于它们的复制可以理解为“真实”复制,即重新开辟栈内存并将原来的值copy一份放进去。那么修改copy的那个值并不会影响原始值,因为它们是独立的。

JavaScript之深浅拷贝

         先看看原始类型和引用类型的存储方式:(图片摘自https://www.cnblogs.com/onlycare/p/9791826.html)

JavaScript之深浅拷贝

        复杂的数据类型即引用类型,它的值是对象,保存在堆内存中,包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针。从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象。

const a = [] b = a console.log("a:",a, "; b:",b) //输出: a: [ ] ; b: [ ] b[0] = 1 console.log("a:",a, "b:",b) //输出: a: [1] ; b: [1] 

上面代码,只是将a的地址给了b,因而对b进行操作,会影响到a的值,这在很多情况下并不是我们想要的。

【浅拷贝】

首先可以通过Object.assign来解决这个问题,很多人认为这个函数是用来深拷贝的。其实并不是,Object.assign只会拷贝所有属性值到新的对象中,如果属性值是对象的话,拷贝的是地址,所以并不是深拷贝。

let a = { age: 1 } let b = Object.assign({}, a) a.age = 2 console.log(b.age) // 1

除了Object.assign之外,我们还可以通过展开运算符 … 来实现浅拷贝,

let a = { age: 1 } let b = {...a} a.age = 2 console.log(b.age) //1

通常来说浅拷贝就能解决大部分问题了,但是当我们遇到如下情况,就会发现浅拷贝无法满足我们的需要了。

let a = { age:1, jobs: { first: 'IT' } } let b = {...a} a.jobs.first = 'PM' console.log(b.jobs.first) // PM

对于第一层拷贝问题,浅拷贝可以解决,但如果接下去的值中还有对象的话,那么两者享有相同的地址。要解决这个问题,就不得不使用深拷贝了。 

 

【深拷贝】

使用JSON.parse(JSON.stringify(a))

let a = { age: 1, jobs: { first: 'IT' } } let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'PM' console.log(b.jobs.first) // IT

难道深拷贝就这么简单?并不是,该方法虽然可以实现深拷贝,但是存在诸多局限:

1、会忽略undifined;2、会忽略symbol;3、不能序列化函数;4、不能解决循环引用的对象。

JSON.parse(JSON.stringify())可以解决大部分深拷贝的问题,更高级的可以用lodash的深拷贝函数

function deepClone(obj){ function isObject(o){ return(typeof o === 'object' || typeof o === 'function') && o !== null } if(!isObject(obj)){ throw new Error('非对象') } let isArray = Array.isArray(obj) let newObj = isArray ? [...obj] : {...obj} Reflect.ownKeys(newObj).forEach(key => { newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key] }) return newObj } let obj = { a: [1, 2, 3], b: { c: 2, d: 3 } } let newObj = deepClone(obj) newObj.b.d = 2 console.log(obj.b.d) // 3

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221568.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午5:48
下一篇 2026年3月17日 下午5:48


相关推荐

  • 也说周鸿祎[通俗易懂]

    也说周鸿祎[通俗易懂]
 最早听说周鸿祎是在林锐的《大学十年》的那篇妙文里。应该是2001年。第一次看完林锐的回忆,觉得这个家伙是个人物,可他居然对周鸿祎服贴得不得了,可见周的确不是一个一般人。没过多久,有媒体开始关注3721了。那个时候,3721还没到过街老鼠人人喊打的时候,一度攻城掠地,风管无限。记得3721最开始吸引眼球的就是和Realname的一场口水大战…

    2022年7月26日
    13
  • JSP热部署的实现原理[通俗易懂]

    JSP热部署的实现原理[通俗易懂]一.             概述名词解释:所谓热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用。对于Java应用程序来说,热部署就是在运行时更新Java类文件。在基于Java的应用服务器实现热部署的过程中,类装入器扮演着重要的角色。大多数基于Java的应用服务器,包括EJB服务器和Servlet容器,都支持热部署。类装入器不能重新装入一个已经装入的类,但只要使用一个

    2022年5月21日
    33
  • Mac 下 JAVA 环境变量的配置

    Mac 下 JAVA 环境变量的配置1.先点击划红线的这个【小火箭】2.打开你会看到有【其他】这一个栏目,点击打开。3.打开后,你会看到这个【终端】,然后点击4.会呈现出这样的界面当然你别管是什么,紧接着第5步。 5.输入这条命令行【/usr/libexec/java_home-V】查看默认的jdk下载地址注意:命令行终端是区分大小写的(-v是不对的,必须是大写-V)…

    2022年6月17日
    36
  • SSL工作原理

    SSL工作原理

    2021年9月22日
    51
  • 毕设代做正规平台_毕设代做被发现会不毕业吗

    毕设代做正规平台_毕设代做被发现会不毕业吗在mac自建一套【学员管理系统】

    2026年2月3日
    43
  • mshtml文档的处理

    objectc=null;myWeb.Navigate(“http://zhidao.baidu.com/”,refc,refc,refc,refc);//…获取WebBroswer中的body代码mshtml.HTMLDocumentClassdoc=(mshtml.HTMLDocumentClass)myWeb.Document;mshtml.HTMLBodybody=(ms…

    2022年4月8日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号