javascript浅拷贝与深拷贝以及对象与json格式的转换json.stringifyjson.parse

冯大少 冯大少     2023-04-13     133

关键词:

   浅拷贝 : 对于引用类型而言,指两个引用类型指向同一个地址,改变一个,另一个也会随之改变。


   例如当设置 ku 的变量值 为 age : 18 , angel 的变量值指向 ku, 在栈内存里,angel 的内存地址和 ku 是一样的,在堆内存里,它们是同一个 object 对象。





   当改变 ku age 的属性值时,angel age的属性值也随之改变。





   深拷贝: 对于引用类型而言,复制后引用类型指向一个新的内存地址,两个对象改变互不影响。


   首先简单介绍 JSON(JavaScript Object Notation)是JavaScript表达值和对象的通用数据格式,其本质就是符合一定规范的字符串。由于JSON的优良特性,非常容易和其他语言进行数据交换,尤其在前后端交互方面。


   在之前的博客也分享了一个关于 JS 反序列化的爬虫项目案例,这里先通过以下序列化和反序列化的例子,说明深拷贝与浅拷贝的区别,接着会详细举例说明序列化和反序列化的各种用法。


   通过 JSON.stringify (序列化) 转化为 JSON 字符串格式





   再通过 JSON.parse (反序列化) ,赋值给 angel, 当 ku age 的改变时, angel age 的值不变。 也就是 在栈内存和堆内存里,ku 和 angel 各自有独立的 内存地址和 object 对象,当发生改变时,两者互不影响。





   == 注意:基础类型的赋值和深拷贝相似,但不属于深拷贝 。==





   使用JSON.stringify(obj)方法会返回该对象obj的JSON字符串数据,但归属于JavaScript语言本身的非数据属性会被JSON.stringify跳过,这包括对象方法、Symbol类型、undefined的属性。



   可见,输出为空的内容



   并非所有的对象都能转为JSON格式,如果对象之间存在循环引用,就会导致转换失败。失败的原因是由于 teacher 引用了 student, student 反过来又引用了 teacher。





   如果想只将对象的个别属性转为JSON格式,或者摆出循环应用中的属性,可以 通过 let json = JSON.stringify(obj[,replacer,space]),其中参数 obj : 要编码的对象;replacer:要编码的属性数组或者映射函数function(k,v);space:用于格式化的空格数量。



  



   如果想要在第二个参数传入一个数组,那么JSON.stringify就会只把数组中的名称转为JSON格式,这样计算对象存在循环引用,同样能够成功的转格式。


   如果我们希望序列化出循环应用外的所有对象属性,只需要把对象的所有属性名写入数组即可,这对对象的子对象同样生效。


   执行结果如下,但还存在一个问题,如果对象属性特别多,可能数组就会非常长,代码也会很冗长,这种情况下就需要使用映射函数。





   映射函数: 我们可以创建一个函数,代替数组作为replacer,这个函数接收(key,value)作为参数,并决定如何序列化对应的属性。


   例如,在解决循环引用的时候,我们排除引用属性。由于值为undefined的属性会被JSON.stringify忽略,这样我们就可以轻松的排除所有不希望出现的属性了。



   格式化使用的空格数量: JSON.stringify(value, replacer, spaces)的第三个参数spaces可以指定JSON字符串的缩进空格数,常用的数值有2、4两种。在以上例子中,没有指定缩进空格数量,所以格式化后的JSON字符串都是没有格式的。


   这样输出的缩进更加清晰







   自定义toJSON方法: 和toString一样,对象的toJSON方法会在序列化的时候调用,我们可以通过重写这个方法改变序列化的方式。


   可以看到,在重写了对象的toJSON方法后,使用stringify的结果发生了改变。我们可以根据自己的需要重写toJSON方法,从而达到要的结果。







   JSON.parse: 之前简单介绍了反序列化的例子,现在就详细介绍如何把JSON字符串转为对象。语法:let obj = JSON.parse(str,[reviver]) 。 str 要解析的 JSON 字符串; reviver 可选的函数 function(key,value),该函数将为每个 (key, value) 对调用,并可以对值进行转换。







   使用reviver, 例如当我们要将字符串’“title”:“Conference”,“date”:“2017-11-30T12:00:00.000Z”’ 转为对象,结果会遇到报错。原因是date属性被转为了字符串,而不是Date对象。





   这就需要使用reviver函数将date转为Date对象:





   receiver 也可用于嵌套对象



javalist复制:浅拷贝与深拷贝

Java的拷贝可以分为三种:浅拷贝(ShallowCopy)、深拷贝(DeepCopy)、延迟拷贝(LazyCopy)。在java中除了基本数据类型之外(int,long,short等),还存在引用数据类型,例如String以及对象实例。对于基本数据类型,实际上是拷贝它的值,而对... 查看详情

浅拷贝与深拷贝(代码片段)

浅拷贝与深拷贝一、数据类型数据分为基本数据类型(String,Number,boolean,Null,Undefined,Symbol)和对象数据类型。基本数据类型的特点:直接存储在栈(stack)中的数据对象数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在... 查看详情

实现浅拷贝与深拷贝(代码片段)

实现浅拷贝与深拷贝Js包含基本数据类型与引用数据类型两种不同的数据类型的值,深拷贝与浅拷贝的概念只存在于引用数据类型。对于引用类型,浅拷贝是拷贝了指向这个对象堆内存的指针,是拷贝了对原对象引用,深拷贝是... 查看详情

实现浅拷贝与深拷贝(代码片段)

实现浅拷贝与深拷贝Js包含基本数据类型与引用数据类型两种不同的数据类型的值,深拷贝与浅拷贝的概念只存在于引用数据类型。对于引用类型,浅拷贝是拷贝了指向这个对象堆内存的指针,是拷贝了对原对象引用,深拷贝是... 查看详情

js的浅拷贝与深拷贝

浅拷贝//这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,//那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。 functionextendCopy(o){    varcopy={};  ... 查看详情

java之浅拷贝与深拷贝

----?浅拷贝---概念  被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。简单说,浅拷贝就是只复制所考虑的对象,而不复制它所引用的对象---实现方式 继承自java.... 查看详情

javascript浅拷贝与深拷贝以及对象与json格式的转换json.stringifyjson.parse

...xff0c;两个对象改变互不影响。  首先简单介绍JSON(JavaScriptObjectNotation)是JavaScript表达值和对象的通用数据格式,其本质就是符合一定规范的字符串。由于JSON的优良特性,非常容易和其他语言进行数据交换,... 查看详情

浅拷贝与深拷贝

浅拷贝:对一个对象进行浅拷贝其实是新创建一个类型跟原对象一样,其内容是原来对象的引用。有以下几种方式实施(1)完全切片操作[:];(2)利用工厂函数,比如list(),dict()等;(3)使用copy模块的copy函数。举个实例:#encoding=UT... 查看详情

javascript数组对象的浅拷贝与深拷贝深浅拷贝的区别+图解原理(代码片段)

JavaScript数组对象的浅拷贝和深拷贝知识回调(不懂就看这儿!)场景复现底层知识与原理1.关于内存(图解)2.关于数据类型3.关于赋值的原理深拷贝与浅拷贝浅拷贝实现原理(图解)深拷贝实现原理&#x... 查看详情

浅拷贝与深拷贝(代码片段)

...js的深浅拷贝,我们先来理解一些js基本的概念##数据类型javascript中的数据分为基本数据类型(String,Number,Boolean,Null,Undefined,Symbol)和复杂的数据类型(也称作引用数据类型-Object)。当一个变量存放基本数据类型时与复杂的数据类... 查看详情

浅谈js中的浅拷贝与深拷贝

  前端工程师应该都比较熟悉浅拷贝和深拷贝的概念,在日常业务代码的过程中,特别是做数据处理的时候,经常行的会遇到,比如如何在不修改原对象的基础上,重新生成一个一模一样的对象,加以利用,又或是,如何巧妙... 查看详情

浅拷贝与深拷贝的实现方式区别;deepcopy如果你来设计,如何实现

浅拷贝与深拷贝的实现方式、区别;deepcopy如果你来设计,如何实现;copy浅拷贝:没有拷贝子对象,所以原始数据改变,子对象改变deepcopy深拷贝:包含对象里面的子对象的拷贝,所以原始对象的改变不会造成深拷贝里的任何子... 查看详情

java引用类型的浅拷贝与深拷贝理解

1.浅拷贝只会复制地址值,也就是同一个对象两个引用,只是复制了一个引用而已。  2.深拷贝重新在堆里创建一个新对象给新引用,连同地址值也不一样。  首先要知道Object的clone()方法,1publicclassTestimplementsCloneabl... 查看详情

java专题十九:浅拷贝与深拷贝

Java专题十九:浅拷贝与深拷贝目录Java专题十九:浅拷贝与深拷贝19.1.clone方法19.2.浅拷贝19.3.深拷贝19.4.实现方法19.4.1.浅拷贝19.4.1.1.使用shalldowCopy方法19.4.1.2.使用clone方法19.4.2.深拷贝19.4.2.1.使用deepCopy方法19.4.2.2.使用clone方法19.1.cl... 查看详情

浅拷贝与深拷贝(代码片段)

... 1.赋值 python中的赋值是对象的引用,python并没有拷贝这个对象,只是指向了被引用对象的内存地址。1a=[1,2,3]23b=a45print(id(a))68196059278print(id(b))981960592  a与b指向的是同一个内存地址,改变a中的值,b同样会改变。1a=[1,2... 查看详情

彻底讲明白浅拷贝与深拷贝

...先检索其在栈中的地址,取得地址后从堆中获得实体。深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。深拷贝和浅拷贝的示意图大致如下:浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享... 查看详情

qimage的浅拷贝与深拷贝

 首先简单说说什么是浅拷贝和深拷贝:浅拷贝就比如像引用类型,而深拷贝就比如值类型,即浅拷贝是共用一块内存的,而深拷贝是复制一份内容。  我们再来看看QImage类的几个构造函数://浅拷贝QImage(uchar*data,intwidt... 查看详情

markdownvector的浅拷贝与深拷贝(代码片段)

查看详情