对javascript中浅拷贝和深拷贝以及赋值的理解
程序员文章站
2022-06-16 10:29:33
...
JS浅拷贝的概念MDN官方并没有给出明确定义,网上很多文章也容易误导人,浅拷贝不单单是指向同一个对象。
另外一个博主总结的拷贝Tz一号
先从赋值说起:
1.赋值
赋值是将某一数值或对象赋给某个变量的过程,分为:
- 1.1、基本数据类型:赋值,赋值之后两个变量互不影响
let a=1;
let b=1;
console.log(a);//1
console.log(b);//1
//基本数据类型不会相互影响
- 1.2、引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有影响
let a=[1,4,5,6];
let b=a;
console.log(a);//1,4,5,6
console.log(b);//1,4,5,6
b[0]=8;
console.log(a);//8,4,5,6
console.log(b);//8,4,5,6
//引用数据类型会改变相应的值
2.浅拷贝
这里给出一个的定义:
创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
注意:
区分开浅复制和引用对象的赋值
浅复制也会创建新的对象
浅拷贝只解决了第一层的问题,拷贝第一层的基本类型值,以及第一层的引用类型地址
- 2.1引用对象的赋值
let a=[1,4,5,6];
let b=a;
//直接把a的引用地址复制给了b
- 2.2浅拷贝
let obj={
a:"harvey",
b:{
name:"good"
}
}
let obj2={...obj};//展开语法
console.log(obj2);
// {
// a:"harvey",
// b:{
// name:"good"
// }
// }
obj2.a="wei";
obj2.b.name="bad";
console.log(obj);
// {
// a:"harvey",
// b:{
// name:"bad"
// }
// }
可以看出,当改变obj2的a和b.name时,a的值未发生改变,b的name发生了改变
**说明浅拷贝改变第一层的值不会改变原始数据**
2.3浅拷贝过程
let obj={
name:"harvey",
a:["ss","dd"],
b:"123",
}
let obj2=scopy(obj);
function scopy(s){
let newobj={};
for(let p in s){
if(s.hasOwnProperty(p)){
newobj[p]=s[p];
}
}
return newobj;
}
console.log(obj2);
2.4常用的浅拷贝
Array.from()方法,Object.assign()方法,展开式语法, Array.prototype.slice方法。
3.深拷贝
3.1 定义
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。
3.2深拷贝=浅拷贝+递归
浅拷贝只是第一层不会和原是数据相互影响,深拷贝每一层都不会相互影响,所以每一层都进行了复制
function scopy(s){
let newobj={};
for(let p in s){
if(s.hasOwnProperty(p)){
if(typeof s[p] === 'object'){
newobj[p]=scopy(s[p]);
}
else {
newobj[p]=s[p];
}
}
}
return newobj;
}
3.3 常用的深拷贝场景
JSON.parse(JSON.stringify(object))
jQuery.extend()
lodash.cloneDeep()