分类专栏: web前端
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36662470/article/details/81490841
一、堆栈的概念
在计算机领域中,堆栈是两种数据结构。
- 堆:队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
- 栈:先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
二、js的数据类型
js的数据类型主要分为两种:基本类型值和引用类型值。
- 基本类型值 有5种:undefined,null,boolean,number,string。这五种数据类型是按值访问的,是存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。
var str1 = "I am string", num1 = 10, bool1 = true, u1 = undefined, n1 = null; //复制变量值 var str2 = str1, num2 = num1, bool2 = bool1, u2 = u1, n2 = n1; //修改变量值 str2 = "Are you new"; num2 = 20; bool2 = false;
可以看到,基本类型值的复制是值的传递,赋值以后二者再无关联,修改其中一个不会影响另一个。
- 引用类型值: 5种基本类型值以外的数据类型都可以看做是引用类型值,比如array,object等,是保存在堆内存中的对象。js不允许直接访问堆内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际是在操作对象的引用而不是实际的对象,是按地址访问的。
var obj1 = { a: "test a" }, arr1 = [2, 5, 6]; var obj2 = obj1, arr2 = arr1; //修改变量值 obj2.a = "change value"; arr1[1] = 48;
可以看到,直接传递引用类性值的时候,传递的只是引用,二者指向同一块内存,所以修改其中一个,必然会引起另一个变量的变化。
在日常的使用中,我们把对象赋值给一个变量时,通常希望得到的是一个跟原对象无关的副本,修改新的变量不影响原对象,因此就有了浅拷贝和深拷贝。
三、浅拷贝和深拷贝
简单的说,浅拷贝就是只将对象 最外层 的键值复制为一个新的对象,而深拷贝则会 递归复制所有的层 ,直到该键的值为基本类型值。 再简单点说 ,经过浅拷贝后,新旧变量可能还会有所关联(既然说了是可能还有所关联,那也可能毫无关联吧,这里的关键就在于原对象的复杂程度了);而经过深拷贝后,理论上,新旧变量再无关联。 注意 ,在进行深拷贝时,层级不宜过多。所以,一般的深拷贝也并不是绝对毫无关联的。
var obj = { a: "a is a", arr: [ 1, 2, 3] }, obj1 = { ...obj }, //假装这里是个浅拷贝 obj2 = JSON.parse(JSON.stringify(obj)); //假装这里是深拷贝。 obj1.a = "value a"; obj1.arr[0] = 66;
可以看到,当原对象的值为 基本类型值 时,浅拷贝和深拷贝并没有区别;而当原对象的某些值为 引用类型值 时,如果修改变量的值,浅拷贝会改变原对象的值,而深拷贝则不会。