#过年不停更# 前端JavaScript深浅拷贝理解 原创
春节不停更,此文正在参加「星光计划-春节更帖活动」
相信小伙伴们经常会听到前端面试中提到深浅拷贝的问题,这里给大家分享一下我的理解
在js中有基本数据类型和复杂数据类型
基本数据类型存储在栈中,而复杂数据类型存储在堆中通过指针指向地址相连接
下面用代码来理解一下
var arr = [1,2,3];
var newArr = arr;
console.log(arr,newArr); // [ 1, 2, 3 ] [ 1, 2, 3 ]
如果我们给newArr末尾添加一个4 再打印一下会出现什么结果
var arr = [1,2,3];
var newArr = arr;
newArr.push(4)
console.log(arr,newArr); //[ 1, 2, 3, 4 ] [ 1, 2, 3, 4 ]
你会发现明明只给newArr添加了数据为什么arr也跟着增加了数据,这是因为:我们在创建了arr这个数组的时候,产生了一个指针指向这个数组,同时我们吧arr的指针共享给了newArr,他们就存在一个相同的指针同时指向同一个数组,得出一个结论,复杂数据类型在赋值的时候是共享内存空间的。很好理解
同理基本数据类型是不会存在共享内存空间这种情况的
var a = 1;
var b = a;
b = 2;
console.log(a,b); //1,2
很容易得得出了一个结论,基本数据类型是独立的,而复杂数据类型是共享的
基本数据类型:一般是浅拷贝,数据相互独立,互不影响
复杂数据类型:一般不是独立,相互影响
深拷贝和浅拷贝的区别
b复制a,当a修改时,b如果变了,浅拷贝,b没变,深拷贝
深拷贝
我们用代码实现一下深拷贝:
递归的方法
//递归的方法实现深拷贝
let a = [1,2,3,4]; //{}
let b = deepClone(a);
a[0]=22
console.log(a,b);
function deepClone(obj) {
let objClone = Array.isArray(obj)?[]:{} //判断是不是数组还是对象
if(obj && typeof obj=="object"){ //保证obj存在且是一个对象
for(key in obj){
if(obj.hasOwnProperty(key)) { //如果obj中有key属性
if(obj[key] && obj[key] ==="object") {//判断二维或者是多维数组
//递归调用
objClone[key]=deepClone(obj[key])
}else{//一维数组
objClone[key] = obj[key]
}
}
}
}
return objClone;
}
这样打印出的结果是:[ 22, 2, 3, 4 ] [ 1, 2, 3, 4 ],很明显a发生改变了而b没改变,这就实现了深拷贝 深拷贝的核心就是要拷贝没个层级 中的属性和内容
当然有同学投机取巧,用js的slice方法实现拷贝,但是如果只是一维数组,是符合条件的,但是如果是多维数组,在改变值的时候,会跟着改变,这样就不叫深拷拷贝了,比如以下代码
let a = [1,2,3,4]
let b = a.slice()
a[0]=22
console.log(a,b);//[ 22, 2, 3, 4 ] [ 1, 2, 3, 4 ]
乍一看很符合条件嘛 a变b不变,但是如果a为多维数组
let a = [1,2,[3,5],4]
let b = a.slice()
a[0]=22
a[2][0]=33
console.log(a,b);//[ 22, 2, [ 33, 5 ], 4 ] [ 1, 2, [ 33, 5 ], 4 ]
显然就不符合多维数组的概念
用parse和stringfy也可以实现深拷贝
let a = [1,2,[3,4],5];
let b = deepClone(a)
a[0]=22;
a[2][0]=333
console.log(a,b); //[ 22, 2, [ 333, 4 ], 5 ] [ 1, 2, [ 3, 4 ], 5 ]
function deepClone(obj) {
let _obj = JSON.stringify(obj)
let objClone = JSON.parse(_obj)
return objClone;
}
这种方法不仅代码少而且性能好,推荐大家使用。
浅拷贝
1.对复杂类型赋值本身就是浅拷贝
2.es6的语法实现
Object.assign({},{})
Array.form()这里就不多演示了 钱拷贝比较简单主要符合前面a变b也变就是浅拷贝,咱们重点还是深拷贝,因为在面试中深拷贝是绝对迈不过去的坎,大家写程序时紧咬住ab的变化,就是共享内存空间,实际上指向同一个内存地址。
那么关于深浅拷贝的就分享到这儿