在ES6中扩展操作符(…)与Object.assign()中复制是浅拷贝,所谓的浅拷贝和深拷贝:
浅拷贝,是在拷贝过程中,遍历时那部分为对象/数组类型指向原来的地址。即修改其中任意的值,另一个值都会随之变化
深拷贝,则是完全开辟新的内存地址。即将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变
1、浅拷贝
浅拷贝: 只做一个最外层的拷贝. 如果拷贝的对象是引用型数据类型,则意味着交出了内存地址,因而在浅拷贝成功的对象身上对引用型数据进行修改时,就会影响到 原来的拓本
let obj = {
a: 1,
b: [1, 2, {a:3}],
c: {a:3}
}
obj.c.a = 4
let obj1 = {
a: obj.a,
b: obj.b
}
obj1.b.push(1) // 切记不要
obj1.b = 123 这样是重新赋值 不是改变原地址的对象
console.log(obj.b) //将会被改变
ES6方法:
let obj2 = Object.assign({},obj)
console.log(obj2) // {a: 1,b: [1, 2, {a:3}],c:{a:4}
let obj3 = {...obj}
conosle.log(obj3) // {a: 1,b: [1, 2, {a:3}],c:{a:4}
2、深拷贝
深拷贝: 里里外外全部拷贝,完全复制,保证引用型数据 依旧是引用型,但不拿地址,只模仿你的面,因此扩展上没有问题,不会冲突
let obj1 = {
a: 1,
b: [1, 2, {a:3}],
c: {a:3}
}
//完全复制 完美复制 但是一个一个去复制,太麻烦啦 我们来一个专门深浅复制的函数
obj1.c.a = 4
let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2) // {a: 1,b: [1, 2, {a:3}],c:{a:3}
自制深复制函数
1.需求 参数1传入拓本 输出拷贝品
let obj = { //拓本
a: 1,
b: [1,2,3,{a: "我"}],
c: {d: 5}
}
function extend (o1) {
var obj1 = {}
if (o1 instanceof Array) { //判断对象是否是数组
obj1 = []
}
for(var key in o1){
var value = o1[key] // 拓本中的值
// value内还有引用型数据&& value不为 null 则 需要对value这个对象 再进来 深拷贝一份 返回出来深拷贝后的值
// obj1[key] = extend(value)
if(typeof value ==="object" && value !== null){
obj1[key] = extend(value)
}else{
obj1[key] = value
}
}
return obj1
}
let obj2 = extend(obj) // 深拷贝测试
obj2.b.push("最后")
console.log(obj2)
console.log(obj) // 深拷贝 不影响拓本 浅拷贝 拓本一起变