javascript教程 - 基本类型值和引用类型值详解

文章标签: javascript教程
2014-11-5 16:20:16     10 人阅读    

一、基本类型值和引用类型值
基本类型值:保存在栈内存中的简单数据字段,5种基本类型值为Undefined、Null、Boolean、Number和String,它们完全保存在内存中的一个位置,访问它们的时候是按值访问的。
引用类型值:保存在堆内存中的对象,即变量中保存的实际上是一个指针,此指针指向内存中的另一个位置,该位置保存对象。当查询引用类型的变量时,先从栈中读取内存地址,然后再“顺藤摸瓜”找到保存在堆中的值,即引用类型是按引用访问,我们操作的不是实际的值,而是那个值所引用的对象。
保存在栈内存中的每个值可以按照顺序访问它们,而在堆中的值则不能,因为每个对象所需要的内存空间并不相等。
1、动态属性
对于引用类型的值,可以为其添加属性和方法,也可以改变或删除其属性和方法:


var person = new Object();
person.name = 'chemdemo';
alert(person.name);//chemdemo
创建一个对象并保存在person变量中,为对象添加属性。如果对象不被销毁或这个属性不被删除,这个属性将一直存在。
但是不能给基本类型添加属性或方法(尽管这样做不会导致任何错误):

 

var person = 'me';
person.name = 'chemdemo';
alert(person.name);//undefined


2、复制变量值
从一个变量向另一个变量复制基本类型值和引用类型值时,也存在不同。
复制基本类型值,会在栈中创建一个新值,然后把该值复制到为新变量分配的位置上:


var num1 = 5;
var num2 = num1;
复制后,num2中的值与num1中的值是完全独立的,该值只是num1中5的一个副本,即这两个变量可以参与任何操作而不会相互影响。
当复制的是引用类型值时,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象,复制操作结束后,两个变量实际将引用同一个对象,改变其中一个变量都会改变另外一个:

 var obj1 = new Object();
var obj2 = obj1;
obj1.name = 'demo';
alert(obj2.name);//demo


3、传递参数
ECMAScript中所有函数的参数都是按值传递的(即把函数外部的值复制给函数内部的参数,就和把值从一个变量复制给另一个变量一样)。
在向参数传递基本类型值的时候,被传递的值会复制给一个局部变量(即命名参数或者说是arguments对象中的一个元素);在向函数传递引用类型值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数外部。

 

 

 

function addTen(num) {
    return num + 10;
}
var count = 20;
var result = addTen(count);
alert(count);//20
alert(result);//30


addTen()函数有一个参数num(局部变量),调用此函数时,count作为参数传递给函数,它的值是20,故数值20被复制给参数num以便在函数中使用。在函数内部,参数num的值被加上了10,但这一变化不会影响到外部变量count(假如num按引用传递的话,count变量的值也应该是30,从而反映函数内部的修改)。
传递的参数是对象:

function setName(obj) {
    obj.name = 'chemdemo';
}
var person = new Object();
setName(person);
alert(person.name);//chemdemo


创建一个对象并保存在变量person中,然后这个对象被传递到函数中又复制给了参数obj,在setName()函数内部,obj变量和person变量引用同一个对象(即即使这个对象是按值传递的,但obj会按引用来访问同一个对象的),所以在函数内部为obj添加属性后,函数外部person变量也有所反映。
下面这个例子进一步证明函数按值传递:

function setName(obj) {
    obj.name = 'demo';
    obj = new Object();
    obj.name = 'chemdemo';
}
var person = new Object();
setName(person);
alert(person.name);//demo


如果person是按引用传递的,那么person就会自动修改为指向其name属性值为"chemdemo"的新对象。实际上,当在函数内部重写obj时,这个变量的引用就是一个局部对象了,而这个局部变量会在函数执行完毕后立即被销毁。
注:可以把ECMAScript函数的参数想象成局部变量。
4、检测类型
要想检测一个变量是什么类型的简单数据类型,最佳工具是使用typeof操作符(如果变量的值是null或对象,则typeof会返回"object"):

 var s = 'chemdemo';
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
 
alert(typeof s);//string
alert(typeof b);//boolean
alert(typeof i);//number
alert(typeof u);//undefined
alert(typeof n);//object
alert(typeof o);//object


检测引用值时,则使用instanceof操作符:

alert(person instanceof Object);//变量person是Object吗?
alert(colors instanceof Array);//变量person是Array吗?
alert(pattern instanceof RegExp);//变量person是RegExp吗?
根据规定,所有引用类型的值都是Object的实例(故检测一个引用类型和Object构造函数时,instanceof操作符始终返回true)。
注:instanceof操作符检测基本类型值时,始终返回false(基本类型不是对象)。


原文地址:http://www.itmmd.com/201411/128.html
该文章由 萌萌的IT人 整理发布,转载须标明出处。

javascript教程-变量的执行环境和作用域   上一篇
下一篇  .htaccess 文件不起作用?| (Apache Rewrite)

精彩回复
发表评论
姓名:       

《程序员app》专门为程序员量身定做!