引用数据类型与堆内存空间
引用数据类型(Object)的值是保存在堆内存空间中的对象。在JavaScript中不允许直接访问堆内存空间中的数据,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用数据类型都是按引用访问的。这里的引用,我们可以理解为保存在变量对象中的一个地址,该地址与堆内存中的对象相关联。
为了更好的理解变量对象与堆内存,我们结合以下的例子与图解配合理解。
function foo() {
var a1 = 10;
var a2 = 'hello';
var a3 = null;
var b = { m: 20 };
var c = [1, 2, 3];
}
如图所示,当我们想要访问堆内存空间中的引用数据类型时,实际上我们是通过一个引用(地址指针)来访问的。
在前端面试题中,我们常常会碰到这样一个类似的题目。
// demo01.js
var a = 20;
var b = a;
b = 30;
// 这时a的值是多少?
// demo02.js
var m = { a: 10, b: 20 }
var n = m;
n.a = 15;
// 这时m.a的值是多少
demo01中,基础数据类型发生了一次复制行为。demo02中,是引用数据类型发生了一次复制行为。
当变量对象中的数据发生复制行为时,新的变量会分配到一个新的值。demo01中,通过`var b = a;` 发生复制之后,虽然a与b的值都等于20了,但是他们其实已经是相互独立互不影响的值了。因此当我们修改了b的值以后,a的值并不会发生变化。具体如下图所示。
在demo02中,通过`var n = m`发生了一次复制行为。引用类型的复制同样会为新的变量自动分配一个新的值保存在变量对象中。但不同的是,这个新的值,仅仅只是引用类型的一个地址指针。当地址指针相同时,尽管他们相互独立,但是它们指向的具体对象实际上是同一个。
因此,当我修改n时,m也会发生变化。这就是引用类型的特性。具体如下图所示。