深浅拷贝
一.概念
其实一般来说,我们遇到深浅拷贝的问题,都是针对引用数据类型的变量操作.先了解下数据类型
1.值类型和引用类型
值类型:直接存储其值,在内存中,是存在栈内存中引用类型: 存储对值的引用,在内存中,是存在堆内存中,变量本身仅仅是一个指向堆中的实际数据地址,存在栈内存中(说白了,就是引用数据类型,实际上存在堆内存中,杂乱无序的放着,但是会有一个指针,指向堆内存中的地址, 而这个指针则是在栈内存中存储)
1.1值类型
Boolean
String
Undefined
Null (typeof 去判断时,会是object,因为null被转换成机器语言时很多个0,而只要前三个为0的话,就会被机器语言判断为object)
Number
Symbol(ES6 唯一性)
1.2 引用类型
Object
Array
Function
RegExp
Date
Function
1.浅拷贝
浅拷贝拷贝的是对象的指针,没有新建空间地址,新老对象共用的同一份地址,指向对内存中同一个地方,修改原来的对象会影响新对象
var obj1={
a:1
}
var obj2=obj1;
obj2.a=5;
console.log('obj1.a',obj1.a); //5
console.log('obj2.a',obj2.a); //5
上述代码,就是一个浅拷贝,对象通过等于号直接赋值,是一个浅拷贝,obj1对象赋值给了obj2,实际上obj2只是拷贝了obj1在内存中栈中的一个地址,也就是指针,他们俩会共同指向堆中数据
2.深拷贝
深拷贝会在内存中,开辟一个相同的空间地址,并且复制相同的数值,两者互不干扰
2.1JSON.parse+JSON.stringify
用JSON.stringify把对象转为字符串,再用JSON.parse把字符串转为新的对象.
var obj3 = {
classId: 2001,
userinfo: {
name: 'liuqiao',
age: '27'
}
}
var obj4 = JSON.parse(JSON.stringify(obj3));
obj4.userinfo.name='zhangsan';
console.log(obj3.userinfo.name); //liuqiao
console.log(obj4.userinfo.name); //zhangsan
局限性:Number,String,Boolean,Array,可以转为JSON对象,但是function这种不行
2.2 lodash 实现深拷贝
lodash是一个高性能的 JavaScript 实用工具库,里面的lodash.cloneDeep()实现深拷贝,原理也是递归实现的
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
<script>
var obj3 = {
classId: 2001,
userinfo: {
name: 'liuqiao',
age: '27'
}
}
var obj4 = _.cloneDeep(obj3);
obj4.userinfo.name = 'zhangsan';
console.log(obj3.userinfo.name); //liuqiao
console.log(obj4.userinfo.name); //zhangsan
</script>
2.3Object.assign()
实际上Object.assign是一个浅拷贝,但是如果是数据结构只有一层,可以实现深拷贝
var obj6={};
var obj5={
a:1
}
obj6= Object.assign(obj6);
obj6.a=2;
console.log(obj6.a); //2
console.log(obj5.a); //1
Object.assign,如果数据结构有多层,则是浅拷贝
var obj3 = {
classId: 2001,
userinfo: {
name: 'liuqiao',
age: '27'
}
}
var obj4={};
obj4= Object.assign({},obj3);
obj4.userinfo.name = 'zhangsan';
console.log(obj3.userinfo.name); //zhangsan
console.log(obj4.userinfo.name); //zhangsan
2.5 ES6扩展运算符 …
与Object.assign() 一样,如果数据结构只有一层,是深拷贝,多层结构了是浅拷贝,只能拷贝第一层的
扩展运算符浅拷贝
var obj3 = {
classId: 2001,
userinfo: {
name: 'liuqiao',
age: '27'
}
}
obj4 = { ...obj3 }
obj4.userinfo.name = 'zhangsan';
obj4.classId=3004;
console.log(obj3.userinfo.name); //zhangsan
console.log(obj4.userinfo.name); //zhangsan
console.log(obj3.classId); //2001
console.log(obj4.classId); //3004
扩展运算符深拷贝
var obj6 = {};
var obj5 = {
a: 1
}
obj6 = { ...obj5 };
obj6.a = 2;
console.log(obj6.a); //2
console.log(obj5.a); //1
二.总结
实际项目中,根据不同的业务场景,判断是否需要使用深拷贝,方式有很多种,根据需求来自己实现即可!