看一个例子:
var a =3; var b = a; a=1; console.log(a,b); var arr1 = [1,2,3,4]; var arr2 = arr1; arr1.push(5); console.log(arr2);
第一个console.log(a,b) 1 3;
第二个console.log(arr2) [1,2,3,4,5]
这个问题很奇怪。为什么 b的值变成了 a 原来的值,没有随着a的重新赋值而变化,而 arr2却随着 arr1的变化而变化呢?
原始值:String,Undefined、Null、Boolean、Number
引用值:Object Array Function Date RegExp
所以很显然了,a 和 b 是属于Number类型的,即原始值;而 arr1 和 arr2是属于 Array 类型的,即引用值;
原始值存储在 栈 中;
引用值存储在 堆 中;并且 在 栈 中存储了 堆 的地址;如下图所示:
所以,两种值的存储方式不同,导致了问题的发生。
原始类型中:
var a =3; //在栈中 开辟空间存放3 并且名称为a var b = a; // 在栈中 开辟空间存放复制 a 的值 并且名称为b a=1; //在栈中 开辟空间存放3 并且名称为a,原来的地址 a 改为默认的地址,这里是默认的1008,如上图所示; console.log(a,b);
引用类型中:
var arr1 = [1,2,3,4];//在堆中 开辟空间存放[1,2,3,4] 并在栈中开辟空间存放 指向对中的地址,栈中名称为 arr1 var arr2 = arr1;// 在栈中开辟空间存放 指向对中的地址,栈中名称为 arr2 这里 arr2存放的堆地址 与 arr1的堆地址相同。 arr1.push(5); console.log(arr2);
那么如果arr1重新赋值,arr2 会随之 arr1的赋值而改变吗?
其实是不会的,原因是,在堆中,arr1的存储过程中,需要重新再开辟一个空间来存放 arr1最新的一次赋值,当然arr1在栈中指向堆的引用地址就发生了改变,这个时候,arr2在栈中的引用地址 和 arr1的地址不同。所以,这个时候,arr2 不会随着 arr1的赋值而改变。
原文:https://www.cnblogs.com/lixiuming521125/p/10867062.html