赋值、浅拷贝和深拷贝
在普通数据类型中,将变量a的值赋值给变量b后,变量a、b是两个值相同但是独立的个体,他们值改变不会影响到对方。因为普通数据类型的值是存放在栈区域,执行b=a后,新开辟一个地址给b,然后把a的值复制到这个地址中,a本身没有受到任何影响。
在引用数据类型中就没有普通数据类型那么简单。
1. 赋值
引用数据类型的值存放在堆区域,它变量名称指向的是值所在堆区域的地址。
当把对象obj赋值给obj2时,赋值的是地址,obj2指向的堆区域内容和obj是同一个。因此当我们修改obj2中的a属性值时,obj也会跟着改变。
var obj = { a: 10 }
obj2 = obj
obj2.a = 20
console.log(obj) //结果为{a: 20}

2. 浅拷贝
浅拷贝就是比赋值多了一层,把对象的值复制一份赋给一个新变量,当对象内的属性值全是基础数据类型时,在新变量上改变属性值,原来的对象不会受到影响。
浅拷贝的实现方法:
(1) Object.assign()
(2) 展开运算符 {…obj}
var obj = {
name: 'rose',
age: 12
}
var newObj = Object.assign({},obj) //或 newObj = {...obj}
newObj.age = 14
console.log(obj.age) //12
console.log(newObj.age) //14
但当对象内存在属性值为引用数据类型时,改变该对象内的引用数据类型的值,原来的对象也会跟着改变。可见,浅拷贝只能拷贝第一层。当对象中的属性值为对象时,拷贝的也是地址。
var obj = {
name: 'rose',
age: 12,
hobby: {dance: true}
}
var newObj = Object.assign({},obj) //或 newObj = {...obj}
newObj.age = 14
newObj.hobby.dance = false
console.log(obj.age) //12
console.log(newObj.age) //14
console.log(newObj.hobby.dance) //false
console.log(obj.hobby.dance) //false
3. 深拷贝
深拷贝是把数据的每一层都拷贝。在新变量上改变值时不会影响到原来的。
深拷贝的实现方式:JSON.parse(JSON.stringify(obj))
该方法的缺点是会忽略undefined和symbol,不能解决循环引用的对象。
var obj = {
name: 'rose',
age: 12,
hobby: {dance: true},
sex: Symbol('sex'),
say: function(){}
}
var newObj = JSON.parse(JSON.stringify(obj))
newObj.age = 14
newObj.hobby.dance = false
console.log(obj.age) //12
console.log(obj.hobby.dance) //true
console.log(newObj) //{name:'rose', age: 14, hobby:{dance: false}}
JSON.parse(JSON.stringify(obj))不能解决循环引用的对象,下边的代码执行会报错。
let obj = {
a: 10,
b: {
c: 20,
d: 30,
},
}
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
版权声明:本文为weixin_44825338原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。