下面看这样一个例子
js
var obj1 = {
data:123,
}
var obj2 = obj1;
obj2.data = 234;
console.log(obj1.data,obj2.data);这个代码会输出一个很奇怪的结果,会输出两个 234,也就是说,我对 obj2 的修改影响到了 obj1 的值。
要解释这个问题,就要提到原始类型和引用类型的区别了,并且涉及到内存相关知识。先介绍原式类型,以整型为例。
当我们声明一个变量的时候,会在内存中开辟一块空的内存空间,比如我们声明了一个名为 a 的变量,如下图所示

此时我们要给 a 赋值为 123,如下图所示

这个时候我声明了一个 b,也就是开辟了一个名为 b 的内存空间,如图所示

接下来再执行 b = a,这个操作本质上就是把 a 内存空间的值丢到 b 内存空间去,如图所示

所以对于非引用类型,并不会产生本文开头所发生的问题,可以用以下代码验证
js
var a = 123;
var b = a;
a = 234;
console.log(a,b);接下来考虑引用类型,引用类型和原始类型不太一样,当我们写一个引用类型的时候,会在内存中开辟一块内存空间来存放这个引用类型,当我们要把这个引用类型赋值给一个变量的时候,会将存放该引用类型的地址赋值给新变量。
接下来解释这个过程,用 var obj = {name:123,} 来解释,首先这是一个语法糖,实际上是两步,即 var obj; 和 obj = {name:123};
首先,var obj 开辟了一个内存空间。

接下来,obj = {name:123},首先,这里我们赋值的是一个对象,这是一个引用类型,所以会现在内存中再开辟一个新的内存空间来存放这个对象

那这里的 ab22H 是什么呢,这叫地址,每一个内存空间都有一块地址,通过这个地址就可以找到这个内存空间,在 JS 中是看不到其真实地址的,所以这个地址也是我瞎写的。
当我们要把一个引用类型赋值给变量的时候,实际上就是把存放引用类型这块内存空间的地址赋值给这个变量,如下图所示

这个时候,如果我们要访问 obj,发现 obj 里面存放的东西是一个地址,此时就会去访问 obj 里面的地址所指向的那块内存空间,也就是真实对象的存放地址。
接下来考虑这样一个操作 obj2 = obj,这个操作也是将 obj 变量中的内容直接复制到 obj2 中,如下所示

此时 obj 和 obj2 的内容是一样的,但这两个东西存放的都是一个内存地址,都指向同一块内存空间,不管是对 obj 还是 obj2 的操作本质上都是对 ab22H 这个内存块的操作,所以我们对 obj 的修改是可以影响到 obj2 的,反之,我们对 obj2 的修改也可以影响到 obj
在 JS 中,字符串并非引用类型,这一点和 C 语言不同
接下来再看一个例子
js
var obj = {
data = 123;
}
var obj2 = obj;
obj = {
data = 234;
}
console.log(obj.data,obj2.data);分析一下这个代码,首先,开辟了一个内存空间用于存放对象,然后将变量 obj 的值赋值为这个内存空间的地址。

下面新建了一个变量 obj2,然后把 obj 的值赋值给 obj2

但此时就不一样了,我将 obj 赋值为一个新的对象,此时会在内存区新开辟一个区域来保存这个新对象,之后再将新对象的地址放到 obj 中去。

从这里我们能看出,此时 obj 和 obj2 中保存的其实并不是同一个对象的地址,是相互独立的,二者就没有关系了。
凡是代码中出现了对象字面量,都会在内存中新开辟一个空间用来存储这个对象
在目前阶段,只有对象字面量才会创建新的对象,也就是说代码中每包含一个对象字面量就会创建一个新的对象, 哪怕两个字面量对象长得一模一样,这也是两个完全不同的对象。
JS 中的垃圾回收
我们考虑这样一个代码
js
var obj = {name :123,};
var obj = 1;在这个情况下,obj原来指向了一个对象,此时在内存中开辟了一个空间用来存放对象,但后来我的obj又变成了1,此时这个对象就没有任何人指向它了, 也就是说完全找不到这块内存了,这就导致了内存泄漏,为了防止这个问题,垃圾回收期会定期发现这种无法访问到的对象,并在合适的时间释放它。由于在JS中垃圾回收并不是由程序员去做的,垃圾回收是一个全自动的过程,所以程序员一般都无需关心。