关于JS的深拷贝与浅拷贝问题处理

1 let obj1 = {
2     a: 0,
3     b: 0
4 }
5 let obj2 = ''
6 
7 // obj2 = obj1
8 // obj2.a = 10
9 // console.log(obj1, obj2); //{ a: 10, b: 0 } { a: 10, b: 0 }

可以看到,将obj1赋给obj2,我们改变的是obj2,而obj1也跟着改变了,这样肯定是不行的。

为什么会出现这种情况呢?其实,这是一个引用传递而不是值传递,obj1和obj2指向的是同一个内存地址。

如果我们不想让obj1的值跟着联动变化,应该怎么做呢?

 

这边我列举几种方法:

第一种:

可以先把obj1转换成字符串,然后在转换成对象,代码如下:

1 obj2 =JSON.parse(JSON.stringify(obj1))
2 obj2.a = 10
3 console.log(obj1, obj2); //{ a: 0, b: 0 } { a: 10, b: 0 }
这种方法存在很大的问题。虽然他在 * 是得票最多的一个答案,也是本人最喜欢的一个方法。 JSON.stringify() 将编码 JSON 支持的值。包含 Boolean,Number,String,以及对象,数组。其他任何内容都将被特殊处理。 undefined,Function,Symbol 时,它被忽略掉 Infinity,NaN 会被变成 null Date 对象会被转化为 String (默认调用date.toISOString())
问:为什么JSON.stringify() 编码 JSON 支持的值那么少呢? 因为JSON是一个通用的文本格式,和语言无关。设想如果将函数定义也stringify的话,如何判断是哪种语言,并且通过合适的方式将其呈现出来将会变得特别复杂。特别是和语言相关的一些特性,比如JavaScript中的Symbol   第二种: 利用ES6扩展运算符(...) 对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
1 obj2 = {...obj1}
2 obj2.a = 10
3 console.log(obj1, obj2); //{ a: 0, b: 0 } { a: 10, b: 0 }

 

第三种:

Object.assign({},{},{}) 等价于第二种方法

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。(如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性)。

1 obj2 = Object.assign({}, obj1)
2 obj2.a = 10
3 console.log(obj1, obj2); //{ a: 0, b: 0 } { a: 10, b: 0 }

 

第四种:

引入Lodash内置的方法直接使用  --- 推荐

Lodash是一个著名的javascript原生库,不需要引入其他第三方依赖。是一个意在提高开发者效率,提高JS原生方法性能的JS库。简单的说就是,很多方法lodash已经帮你写好了,直接调用就行,不用自己费尽心思去写了,而且可以统一方法的一致性。Lodash使用了一个简单的 _ 符号,就像Jquery的 $ 一样,十分简洁。
1 import * as _ from 'lodash'
2 
3 obj2 = _.cloneDeep(obj1)
4 obj2.a = 10
5 console.log(obj1, obj2); //{ a: 0, b: 0 } { a: 10, b: 0 }

 

 

上一篇:leetcode-148. 排序链表


下一篇:腾讯精选50题—Day12题目146,148,155