为什么出现
由于js对基本数据类型与引用数据类型的处理方式不同
深浅拷贝(复制)一般用于引用类型的复制,不用于基本类型的复制
关于js数据类型
一、 定义(深拷贝&&浅拷贝)
深拷贝,是指拷贝对象的具体内容
是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放对象,且修改新对象不会影响原对象
是创建一个全新的对象,有着原始对象属性值的拷贝。对于属性值就是基本类型,就拷贝基本数据类型的值,如果属性值是引用类型,拷贝的是内存地址
浅拷贝,复制对象时,仅复制对象的引用,不是复制对象本身
其中一个对象的值发生改变,会影响到另外一个对象
let a = { name: '张三', age: 18 }
let b = a
b.name = '李四'
console.log(a) // {name: '李四1', age: 18}
console.log(b) // {name: '李四1', age: 18}
浅拷贝实现方式
二、浅拷贝的实现方式
三、深拷贝的实现方式
1.使用JSON.parse(JSON.stringfy(obj)) 序列化和反序列化
2.使用Object.assign()
将一个或多个源对象的可枚举属性拷贝到目标对象,返回目标对象
let a = { name: '张三', age: 18 }
let aa = { test1: '学生', test2: '初中' }
let b = Object.assign({}, a, aa)
b.name = 'zhangsan'
console.log(a) // {name: '张三', age: 18}
console.log(b) // {name: 'zhangsan', age: 18,test1: '学生', test2: '初中'}
3.使用扩展运算符(...)
既具有深拷贝性质,也具有浅拷贝性质
对于拷贝对象的第一层,属于深拷贝;对于拷贝对象更深层次,属于浅拷贝
扩展运算符是ES6新引入的语法,可用于讲一个对象的所有可枚举属性拷贝到另外一个对象中
let a = {
name: '张三',
age: 18,
test: {
a: '大学生'
}
}
let b = { ...a }
// 更改第一层数据,原对象数据不会改变,属于深拷贝
b.name = '李四'
// 更改第二层的数据,原对象数据也发生改变,属于浅拷贝
b.test.a = '研究生'
console.log(a) // {name: '张三', age: 18, test: {a: '研究生'}}
console.log(b) // {name: '李四', age: 18, test: {a: '研究生'}}
4.使用Array.prototype.concat()
可将一个或多个数组或值合并成一个新数组。将一个对象作为参数传递给concat()方法时,会将该对象作为一个值添加到数组中,从而实现深拷贝
let a = { name: '张三', age: 18 }
let aa = { test1: '学生', test2: '初中' }
let b = [].concat(a)
console.log(b) // [{name: '张三', age: 18},{test1: '学生', test2: '初中'}]
5.使用Array.prototype.slice()
可以用于提取数组中的一部分,并将其作为一个新数组返回。将一个对象作为参数传递给slice()方法时,它会将对象作为一个值添加到数组中,从而实现深拷贝
let a = { name: '张三', age: 18 }
let b = [a].slice()
console.log(a) // {name: '张三', age: 18}
console.log(b) // [{name: '张三', age: 18}]