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 }