首页 > 浅析JS赋值与深浅拷贝
头像
糖师爷
编辑于 2021-01-12 22:58
+ 关注

浅析JS赋值与深浅拷贝

浅析JS赋值与深浅拷贝

说到深浅拷贝,那在这就不得不提一下内存和数据类型了。

在JS当中,数据类型分为基本数据类型和引用类型,其中基本数据类型共六种(string,number,boolean,undefined,null,symnol),引用类型为Object(细分可分为Array、object、date......)。

那么在来说一下内存,内存分为栈内存和堆内存,其中栈内存用来存储基本数据类型和引用类型的地址,而堆内存则存储引用数据类型。

一、赋值

什么是赋值呢,其实赋值分为两种,一种是传值,还有一种是传址,顾名思义,前者传的是基本数据类型的值,比如变量的值、字符串或者是undefined,而后者传递的是引用类型的地址。简单来说就是在栈内存中重新开辟一块新的空间,将需要的值复制一份,那有的同学就要说了,这不就是拷贝么?其实不然,对于传值来说,如果将变量a赋值给变量b,复制的仅仅是值,当你改变b的时候,a不受影响,如图:


但对于传址来说,由于复制的是引用类型的地址,那么不管复制多少次,他指向的堆内存中的内存块没有变,也就是说,复制出来的两个地址指向同一个内存块,不管改变哪个对象,他们的值都会一起改变,如图:


二、拷贝

什么是拷贝?拷贝和赋值究竟有何不同?简单来说,二者最根本的不同就在于操作的对象不同,赋值操作的是基本数据类型,而拷贝操作的是引用数据类型,究其本质就是,前者是对栈内存的数据进行的操作,后者是对堆内存的数据进行的操作。

那么现在假设有一个对象如下所示:
var obj={name:"tom",sex:"man",obj1:{age:15}} 

2.1浅拷贝

所谓浅拷贝,也就是只拷贝对象的第一层,即只拷贝最外层的基本数据类型,对于对象中的其他引用类型则只拷贝其地址,也就是说,以上面的obj为例,浅拷贝过来的应该是:

	
	
	
	
{name:"tom",sex:"man",obj1:{obj1的地址}}

到此为止,你可以随意更改name、sex,源数据不会受到影响,但当你更改obj1的内容时,源数据中的obj1也会随之发生改变

2.2深拷贝

深拷贝理解起来就非常简单了,就是完完全全的拷贝出一个新的对象,不管源数据有几层,通通拷贝成新的对象,与源数据没有一点关系

三、实现方法

3.1、浅拷贝

<1>通过ES6的object.assign()

		
		
		
		
var a={name:"tom"};
var b=Object.assign({},a);

<2>扩展运算符

	
	
	
	
var a={name:"tom"};
var b={...a};

<3>for...in...

	
	
	
	
let copy=(obj)=>{
let result={};
for(var a in obj){
result[a]=obj[a];
}
return result;
}

3.2、深拷贝

<1>解构赋值

	
	
	
	
let a={age:10,address:{city:"shanghai"}};
let b={...a,address:{...a.address}}

<2>递归

		
		
		
		
function deep(obj){
let result=typeof obj.splice= = ='function'?[]:{};
if(obj&&typeof obj = = ="object"){
for(let key in obj){
if(obj[key]&&typeof obj[key]= = ="object"){
result[key]=deep(obj[key]);
}else{
result[key]=obj[key];
}
}
return result;
}
return obj;
}

全部评论

(2) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

近期热帖

近期精华帖

热门推荐