JavaScript变量松散类型的本质,决定了它只是在特定时间保存特定值的一个名字而已。
ECMAScript变量可能包含两种不同数据类型的值:基本类型值,引用类型值。
在将一个值附值给变量时,解析器必须确定这个值到底是基本类型还是引用类型。基本数据类型例如:Undefined Null Boolean Number String,它们都是按值访问的,可以操作保存在变量中的实际值。
引用类型的值是保存在内存中的,与其他语言不同,ECMAScript不允许直接访问内存中的位置,也就是说,不能直接操作对象的内存空间。在操作对象的时候,实际是在操作对象的引用。补充:当复制保存着对象的某个变量时,操做的是这个对象的引用;但是当为该对象添加属性的时候,操作的就是实际的对象了。
动态属性:
定义基本类型和引用类型的方法是类似的:创建一个变量,并且为它赋值。但是,它们其实是很有区别的。例如,引用类型可以添加并修改属性和方法:
var person = new Object();
person.name = "Nicholas";
alert(person.name); //"Nicholas"
但是对于一个基本类型,这就没戏的:
var name = "Nicholas";
name.age = 27;
alert(name.age); //undefined
看到了?根本存不住啊。。。
复制变量:
基本类型的复制是值传递,两个变量做了相等的赋值后,互相不影响。
但是引用类型的复制则是地址传递,相当于是两个“指针”指向了同一个内存,所以对一个变量赋值,另一个也会被改变。
栗子:
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Nicholas";
alert(obj2.name); //"Nicholas"
传递参数:
ECMAScript中,所有函数的参数都是按值传递的。
当参数是基本类型的值的时候:传递的值会被复制给一个局部变量;当参数是引用类型的时候,则会把这个值在内存中的地址复制给一个局部变量。
请看下面这两个例子:
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); //20 不变
alert(result); //30
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
第二个栗子不太好理解,有很多人会认为这恰恰说明了参数是地址传递的。让我们来分析一下:
首先,代码创建了一个object对象,将其保存在了变量person中,然后,这个变量作为参数,复制给了obj。此时,在函数内部,obj和person引用的是同一个对象,也就是说,参数是按照值传递的,但是obj是按引用来访问的person对象。于是,当我们给obj添加新的属性的时候,person对象也会有反应,因为person指向的对象在堆栈中只有一个。
让我们再来看下面这个修改过的栗子,来证明参数传递确实是值传递:
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
如果参数是地址传递,那么最后一行代码的显示值应该是Greg。这说明了, 在函数内部修改了参数的值,但是原引用依旧保持不变,是真正的值传递喔~
检测类型:
检测基本数据类型时,使用typeof函数
var s = "Nicholas";
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
alert(typeof s);//string
alert(typeof i);//number
alert(typeof b);//boolean
alert(typeof u);//undefined
alert(typeof n);//object 很神奇
alert(typeof o);//object
检测引用对象的值,使用instanceof,因为引用对象使用typeof方法,都会返回object,而我们想知道的也许是,它到底是什么类型的对象:
结果会返回true/false
alert(person instanceof Object); //person是不是Object类型的对象?
alert(colors instanceof Array); //colors是不是Array类型的对象?
alert(pattern instanceof RegExp); //pattern是不是RegExp类型的对象?