参考文章:
- [JS]深拷贝与浅拷贝的区别,实现深拷贝的几种方法
- 你所不知道的JSON.stringify
- 彻底讲明白浅拷贝与深拷贝
数据结构和数据存储方式
在聊这个问题之前,我们得先捋一捋JavaScript的数据结构和数据存储方式,JavaScript的数据结构主要分两种。
1.基本数据类型(六种):String、Number、Null、Underfined、Boolean、Symbol
;
2.引用数据类型(三种):Object、Array、Function
;
- 基本数据类型的存储是key和value都存储在栈内存中。
例如let a = 1;
当你用b=a复制a时,会另外开辟了新内存空间存储b。
你此时修改a和b的值,也互相不会影响。
- 而引用类型的存储是key在栈内存中,但是value在堆内存中,栈内存仅仅是存储了堆内存的地址
例如let aArr = [1,2,3,4,5];
这个时候使用bArr=aArr复制aArr时,的确也是开辟了新内存空间存储bArr,但是问题在于,这个时候栈内存中的value值复制给bArr以后,这个只是一个地址罢了,并非具体的值,而这个地址同样的指向了同一个堆内存存储的值。好比一个房子在一街一号,然后另外一个房子也在一街一号,那这俩房子实际上就是同一个房子。
深拷贝和浅拷贝
深拷贝和浅拷贝只是针对Array和Object这种复杂的数据结构来说,对基本数据类型是没有这种说法的。
常见的浅拷贝方法有:
Object.assign()
Array.prototype.concat()
Array.prototype.slice()
常见的深拷贝方法有:
JSON.parse(JSON.stringify())
- 递归
浅拷贝
看到下面这个例子,你是不是以为Object.assign()
是深拷贝?你只看到了第一层,而它在大气层。(手动狗头)
当object的属性只有一层的时候,Object.assign()
是深拷贝,这是因为该对象中属性的值都是基本数据类型,也就是上面讲到的都存储在栈中,拷贝过去的时候就是直接复制了属性的值,但是一旦出现像是下面这种数据结构,属性的值是引用类型Array
或者是Object
的时候就暴露了自己是个浅拷贝的事实。其他两种浅拷贝方法也是同理。
深拷贝
JSON.parse(JSON.stringify())
转成JSON
格式然后反转回来,这种方法固然简单方便,但是JSON
是一个通用的文本格式,和语言无关。设想如果将函数定义也stringify
的话,如何判断是哪种语言,并且通过合适的方式将其呈现出来将会变得特别复杂。特别是和语言相关的一些特性,比如JavaScript
中的Symbol
。诸如此类等等,所以坑非常多一不小心就会翻车,除非是数据结构特别简单一般不建议使用。更详细的说明可以参考 你所不知道的JSON.stringify
递归的思路就是不断的往下查询,直到属性的值的类型是基础数据类型即可。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!