基本类型和引用类型的区别以及在内存中的分配
ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。
主要区别
<基本数据类型 | 引用数据类型 |
---|---|
在栈中进行分配 | 在堆中进行分配 |
变量名指向具体的数值 | 变量名指向存数据对象的内存地址,即变量名指向hash值 |
变量在声明之后java就会立刻分配给他内存空间 | 它以特殊的方式(类似C指针)指向对象实体(具体的值),这类变量声明时不会分配内存,只是存储了一个内存地址 |
基本类型之间的赋值是创建新的拷贝 | 对象之间的赋值只是传递引用 |
“==”和“!=”是在比较值 | “==”和“!=”是在比较两个引用是否相同,需要自己实现equals()方法 |
基本类型变量创建和销毁很快 | 类对象需要JVM去销毁 |
动态的属性
定义基本类型值和引用类型值的方法时类似的:创建一个变量并为该变量赋值。但是对于不同类型值可以执行的操作就不一样了。
引用类型值
我们可以为其添加属性和方法,也可以改变和删除其属性和方法。请看下面的例子:
var person = new Object();
person.name = "Nicholas";//添加属性并且赋值
alert(person.name);//输出Nicholas
上面代码创建了一个对象并将其保存在了变量person中。然后为对象添加了一个名为name的属性并且将字符串“Nicholas”赋给了这个属性。
基本类型值
我们不能给基本类型的值添加属性,尽管这样做并不会出错。例如:
var name = "Nicholas";
name.age = 27;
alert(name.age); //得到:undefind
在这个例子中,我们为字符串name定义了一个名为age的属性,并且赋值27。但在下面使用alert访问这个属性的时候,发现该属性不存在。这说明基本类型不能动态的添加属性。
复制变量值
除了保存方式不同之外,在从一个变量向另一个变量复制基本类型和引用类型值时,也存在不同。
基本类型值
如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值。然后把改制复制到新变量分配的位置上。看一个小例子:
var num1 = 5;
var num2 = num1;
在此,num1中保存的值时5.当使用num1的值来初始化num2时,num2中也保存了值5.但num2中的5与num1中 的5 是完全独立的。该值只是num1中5的一个副本。这两个变量可以参与任何操作而不会相会影响。
引用类型值
当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作以后,这两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。如下面的例子所示:
var obj1 = new object();
var obj2 = obj1;
obj1.name = "Nicholaa";
alert(obj2.name);//输出“Nicholas”
首先,变量obj1保存了一个对象的新实例。然后,这个值被复制到了obj2中;换句话说,obj1和obj2都指向同一个对象。这样,当为obj1添加属性name后,可以通过obj2来访问这个属性,因为这两个变量引用都是同一个对象。具体关系可以看下图:参考文献:JavaScript高级程序设计(第3版)