深浅拷贝
深浅拷贝只针对引用数据类型
浅拷贝--拷贝的是地址
如果是简单数据类型拷贝值,引用数据类型拷贝的是地址
例:浅拷贝,拷贝不了里面的famamily
const obj = {
name: 'ddd',
famaliy: {
}
}
如果是单层对象,没问题,多层对象就有问题
拷贝对象
<script>
const obj = {
name: 'justodit',
age: 15
}
const Just = obj
console.log(obj);
Just.name='JUSTODIT'
console.log(Just);
console.log(obj);//obj里面得name也修改了
</script>
解决办法
1、展开运算符
const obj = {
name: 'justodit',
age: 18
}
//通过展开运算符放到新对象里面
const OBJ = { ...obj }
console.log(OBJ);
OBJ.age=19
console.log(OBJ);//age:19
console.log(obj);//age:18 obj原来的值不会改变
2、Object.assign(空对象,要拷贝得对象)
const obj = {
name: 'justodit',
age: 18
}
const OBJ={}
Object.assign(OBJ,obj)
console.log(OBJ);
OBJ.age=19
console.log(OBJ);//age:19
console.log(obj);//age:18 obj原来的值不会改变
拷贝数组
1、空数组名.concat(要拷贝的数组名)
const arr = [1, 2, 3];
let arr1 = [];
arr1 = arr1.concat(arr);
arr1[0] = 3
console.log(arr1); // 输出: [3, 2, 3]
console.log(arr); // 输出: [1, 2, 3],arr 没有被改变
2、[...arr]
const arr = [1, 2, 3];
let arr1 = [...arr];
arr1[0] = 3
console.log(arr1); // 输出: [3, 2, 3]
console.log(arr); // 输出: [1, 2, 3],arr 没有被改变
直接赋值和浅拷贝的区别
1、直接赋值的话,会互相影响,因为直接把对象或者数组里的地址也复制过去了
2、浅拷贝如果是一层对象就不受影响,多次对象就会互相影响
深拷贝
通过递归函数实现深拷贝
函数递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
1、函数内部自己调用自己
2、递归函数的作用和循环效果类似
3、递归很容易发生“栈溢出”错误(stacK overflow) ,所以必须要加退出条件return
<script>
let i = 1
function fn() {
console.log(`这是第${i}次调用`);
if (i >= 6) {
return
}
i++
fn()
}
fn()
</script>
递归函数使用例子:
<script>
function getTime() {
document.querySelector('div').innerHTML=new Date().toLocaleString()
setTimeout(getTime,1000)
}
getTime()
</script>
深拷贝拷贝出来的对象互不影响
1、要想实现深拷贝用到函数递归
2、当我们在普通拷贝时候,直接赋值就可以
3、如果遇到数组时,我再次调用递归函数
4、如果再次遇到对象,再次调用一次递归
5、先数组后对象 因为数组语属于对象
递归函数进行深拷贝
<script>
const obj = {
uname: 'just',
age: 15,
hobby: ['篮球', ''],
family: {
name:'JUSTODIT'
}
}
const o = {}
function deepCopy(newObj, oldObj) {
for (let key in oldObj) {
//判断属性值是否是数组
//'just'是否属于数组
//15是否属于数组
if (oldObj[key] instanceof Array) {
newObj[key] = []
// 再次递归
deepCopy(newObj[key], oldObj[key])
} else if (oldObj[key] instanceof Object) {
newObj[key] = {}
deepCopy(newObj[key], oldObj[key])
}
else {
//k 属性名 uname age oldObj[k] 属性值 18
// key是属性名 obj[key]属性值
//newObj===o.uname 给对象添加属性
newObj[key] = oldObj[key]
}
}
}
deepCopy(o, obj)
o.age = 12
o.hobby[0] = 'JUST'
o.family.name='anything is possible'
console.log(o);
console.log(obj);
</script>
代码深解释
//第二遍循环---在数组内部的循环
function deepCopy([], ['篮球', '']) {
//key=索引号,oldObj[key] '篮球', ''
for (let key in oldObj) {
//判断属性值是否是数组
//'just'是否属于数组
//15是否属于数组
if (oldObj[key] instanceof Array) {
//newObj[key] 接收 [] hobby
newObj[key] = []
deepCopy(newObj[key], oldObj[key])
} else {
//k 属性名 uname age oldObj[k] 属性值 18
// key是属性名 obj[key]属性值
//newObj===o.uname 给对象添加属性
newObj[0] = '篮球'
newObj[1] = ''
}
}
}
js库lodash里面cloneDeep函数
<!-- 先引用 -->
<script src="./lodash.min.js"></script>
<script>
const obj = {
uname: 'just',
age: 15,
hobby: ['篮球', ''],
family: {
name:'JUSTODIT'
}
}
const deep=_.cloneDeep(obj)
console.log(deep);
deep.family.name='anything is possible'
console.log(deep);
console.log(obj);
</script>
结果:
利用json实现深拷贝
步骤:
1、将对象变为JSON字符串 JSON.stringify(obj)
2、再把JOSN字符串转换为对象
<script>
const obj = {
uname: 'just',
age: 15,
hobby: ['篮球', ''],
family: {
name: 'JUSTODIT'
}
}
//将对象变为JSON字符串 JSON.stringify(obj)
//再把JOSN字符串转换为对象
const deep=JSON.parse(JSON.stringify(obj))
deep.hobby[0]='bsae'
deep.family.name='anything is possible'
console.log(deep);
console.log(obj);
</script>