JS深拷贝和浅拷贝

JS深拷贝和浅拷贝

刘听风 264 2022-06-25

深拷贝与浅拷贝的区别

主要在于复制出来的新对象和原来的对象是否会相互印象,改变一个,另外一个也会改变

浅拷贝:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅拷贝出来的对象也会相应改变

深拷贝:在内存中开辟一块新的地址用于存放复制的对象

区别

  • 深拷贝和浅拷贝的主要区别就是其在内存中的存储数据类型不同。
  • 堆和栈都是内存中划分出来用来存储的区域。
  • 栈(stack)为自动分配的内存空间,它由系统自动释放;
  • 堆(heap)则是动态分配的内存,大小不定也不会自动释放。
基本数据类型
String 字符串 Number数值 Boolean布尔值
Undefined 未定义 Object 对象 Null 空值
引用数据类型
Object 对象

其中String、Number、Boolean、Null、Undefined 属于基本数据类型

基本数据类型存放在栈中

  • 存放在占内存中的简单数据段,数据大小确定,内存空间大小可以分配,它直接按值存放的,所以可以直接访问。
基本数据类型不可变
  • javascript中的原始值与对象(包括数组和函数)有着根本区别。原始值是不可更改的;任何方法都无法更改一个原始值。对数字和布尔值来说显然如此——改变数字的值本身就说不通,而对字符串来说就不那么明显。因为字符串看起来像由字符组成的数组,我们期望可以通过制定索引来假改字符串中的字符。时间上,javascript是禁止这样做的。字符串中所有的方法看上去返回了一个修改后的字符串,实践上返回的是一个新的字符串值。
  • 基本数据类型值不可变。
  • 操作的方法都是返回一个新字符串,并没有改变其原有的数据。

引用类型

  • 引用类型存放在堆中
  • 引用类型(object)是存放在堆内存中的,变量实际上是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要根据情况进行特定的分配。
  • 引用类型是可以直接改变其值的
  • 引用类型的比较是引用的比较
  • 虽然变量a和变量b都是表示一个123的数组,但是其在内存中的位置不一样,也就是说变量a和b指向的不是同一个对象,所以他们是不相等的。

传值和传址

  • 浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。
  • 浅拷贝是对值的复制,对于对象来说,浅拷贝是对对象地址的复制,并没有开辟新的栈,也就是说复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变;
  • 深拷贝则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,并不会改变另一个对象的值

传值

基本数据类型的赋值(=)是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中。
var a = 10;
var b = a;
a ++ ;
console.log(a); // 11
console.log(b); // 10

传址

引用类型的赋值是传址。只是改变指针的指向。
将存放在栈内存中的地址赋值给接收的变量
var a = [1,2,3];
var b = [1,2,3];
b.push(4);
console.log(b);//[1,2,3,4]
console.log(a);[1,2,3,4]