ECMAScript包含两种不同数据类型的值:原始值和引用值。基本类型值是指简单的数据段,而引用类型值是可能有多个值的对象。在进行变量赋值时,解析器必须确定该值是原始类型值还是引用类型值。五种常用的基本数据类型是:Undefined、Null、Boolean、Number和String。原始数据类型按值访问,因为可以操作存储在变量中的实际值。引用类型的值是存储在内存中的对象。JavaScript不允许直接访问内存中的位置,即它不能直接操作对象的内存空间。当操作一个对象时,你实际上是在操作一个对该对象的引用,而不是实际的对象。因此,引用类型的值是通过引用来访问的。1.动态属性对于引用类型的值,我们可以给它添加属性和方法,也可以改变和删除它的属性和方法。例如:varperson=newObject();person.name="John";alert(person.name);//"John"只要对象没有被销毁或者这个属性没有被删除,这个属性就会一直存在。但是我们不能向原始值添加属性,尽管这不会导致任何错误。2.复制变量值如果将一个基本类型的值从一个变量复制到另一个变量,则在变量对象上创建一个新值,然后复制到为新变量分配的位置,例如:varnum1=5;varnum2=num1;//5下图形象地展示了复制基本类型的值的过程:当将引用类型的值从一个变量复制到另一个变量时,存储在变量对象中的值也会被复制到在为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,这个指针指向一个存储在堆上的对象。复制操作之后,两个变量实际上将引用同一个对象。因此,改变其中一个变量会影响另一个变量,例如:varobj1=newObject();varobj2=obj1;obj1.name="John";alert(obj2.name);//"John"3.传递参数ECMAScript中的所有函数参数都是按值传递的。将函数外部的值复制到函数内部的参数就像将一个变量的值复制到另一个变量。传递原始类型的值还是引用类型的值并不重要。这里需要注意的是,变量的访问方式有传值和传引用两种,但是参数只能传值。将原始类型的值传递给参数时,传递的值将复制到局部变量(命名参数)。例如:functionaddTen(num){num+=10;returnnum;}varcount=20;varresult=addTen(count);alert(count);//20,不改变alert(result);//30参数其实是一个函数局部变量。参数num和变量count互不相识,它们只是具有相同的值。如果num是引用传递,那么count的值也会变成30,从而体现函数内部的变化。将引用类型的值传递给参数时,会将该值在内存中的地址复制到一个局部变量中,因此这个局部变量的变化会反映到函数外。例如:functionsetName(obj){obj.name="John";}varperson=newObject();setName(person);alert(person.name);//"John"在这个函数里面,obj和person是指同一个对象。换句话说,即使这个值是按值传递的,obj也会按引用访问同一个对象。所以在函数内容中给obj加上nama属性也是响应函数外的person对象,因为person指向的对象在堆内存中只有一个,而且是一个全局对象。很多开发者认为在函数内容中修改的对象会在全局作用域中体现出来,说明参数是按引用传递的。这种看法其实是错误的。请参见以下代码:functionsetName(obj){obj.name="John";obj=newObject();obj.name="Evan";}varperson=newObject();setName(person);alert(person.name);//"John"如果person是引用传递的,那么person会自动修改为指向一个name属性为"Evan"的新对象,但是当我们访问person.name时,发现它的值还是"John"",这意味着即使在函数内部修改了参数的值,原始引用保持不变。其实在函数内部改写obj的时候,这个变量指的是一个局部对象。而这个局部对象会在函数执行完成后立即被销毁。4.检测类型要检测一个值是否是基本数据类型,typeof操作符是最好的工具。它可以检测变量是字符串、数字、布尔值还是未定义。如果变量是对象或null,则typeof运算符返回对象。但是在检测引用类型的值时,typeof就没那么有用了。通常我们不想知道一个值是一个对象,而是想知道它是什么类型的对象。这时候我们可以使用instanceof操作符。如果变量给定了一个引用类型的实例,则instanceof运算符将返回true。例如:alert(personinstanceofObject);//变量person是Object吗?alert(colorsinstanceofArray);//变量colors是数组吗?alert(patterninstanceofRegExp);//变量patternRegExp?所有引用类型的值都是Object的实例。因此,instanceof在检查引用类型或Object构造函数的值时返回true。当使用instanceof运算符检测一个基本类型的值时,它会返回false,因为基本类型不是对象。
