数之源--值类型和引用类型

来源:互联网 发布:mysql 表分区查询 编辑:程序博客网 时间:2024/05/17 22:54
 

我们还可以从用法的角度对其进行概括。任何语言、任何数据类型,它的数据都可以分为两大类:值类型和引用类型。

值类型:也称为原始数据或原始值(primitive value)。这类值存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表,栈按照后进先出的原则存储数据,先进入的数据被压入栈底,最后插入(push)的数据放在栈顶,需要读取数据时从栈顶开始弹出(pop)数据,即最后一个数据被第一个读出来。因此说,值类型都是简单的数据段。变量的位置和变量值的位置是重叠的,也就是说值类型的数据被存储在变量被访问的位置。

引用类型:这类值存储在堆(heap)中,堆是内存中的动态区域,相当于自留空间,在程序运行期间会动态分配给代码和堆栈。堆中存储的一般都是对象,然后通过一个编号传递给栈内变量,这个编号就是所谓的引用指针(point),这样变量和变量值之间是分离的,它们通过指针相联系。当读写数据时,计算机通过变量的指针找到堆中的数据块,并进行操作。

JavaScript中,number、string、boolean和undefined型数据都是值类型。由于值类型数据占据的空间都是固定的,所以可以把它们存储在狭窄的内存栈区。这种存储方式更方便计算机进行查找和操作,所以执行速度会非常快。

而对于object型数据(包括function和array)来说,由于它们的大小是不固定的,只能被分配到堆区(如果存储在栈区,则会降低计算机寻址的速度)。然后在栈区存储对象在堆区的地址即可,对于变量的性能也没有任何负面影响。

JavaScript语言中,object、function和array等对象都是引用型数据。很多语言都把字符串视为引用型数据,而不是值类型,因为字符串的长度是可变的。但是JavaScript比较特殊,它把字符串作为值类型进行处理。不过,字符串在复制和传递运算中,是以引用型数据的方法来处理的。

当比较两个引用值时,比较的是两个引用地址,看它们引用的原值是否为同一个副本,而不是比较它们的原值字节是否相等

var a = new Number(1);      // 引用值a  
var b = new Number(1);      // 引用值b  
var c = a;                      // 把a的引用赋值给c  
alert(a==b);                  // 返回false  
alert(a==c);                  // 返回true 

值类型是以实际值参与运算的,因此与原数据没有直接联系。而引用型以引用地址参与运算,计算的结果会影响到引用地址所关联的堆区数据块。

var s = "abc";                  // 字符串,值类型数据  
var o = new String(s);      // 字符串对象,被装箱后的字符串  
function f(v){                  // 运算函数  
 v.toString = function(){    // 修改参数的方法toString()  
 return 123;  
   };  
}  
f(s);                          // 传入值  
alert(s);              // 返回字符串"abc",说明运算没有对原数据造成影响  
f(o);                // 传入引用  
alert(o);            // 返回数值123,说明运算已经影响到原数据的内部结构 

原创粉丝点击