2006年9月6日星期三

JavaScript中容易被误解的两个地方

1. js中的变量作用域(Variable Scope)
和java,c++中不同的地方是,js中没有块作用域(Block Scope)。变量的作用域将从声明一直持续到function的结尾。看个例子就会明白了。
function testScope()
{
var a = "a";

function g() { alert(a); }
g(); //这里输出结果为a ,因为a的作用域将持续到function testScope的结尾


for(var i=0; i<2; i++)
{
var a = "a is changed"; //这里的变量a将覆盖开始声明的变量a
var b = "b"; //b的作用域从声明一直到function的结尾

}

alert(a); // 输出结果为 a is changed, js首先查找到的a是在循环中定义的那个
alert(b); // 输出为 b 在java中,此时将访问不到变量b,b已经出了作用域,但是在js中是可以的.


}


2. js中的垃圾回收(garbage collection)
js也是一门采用垃圾回收机制的语言,和java一样。js的解释器负责分配和回收内存。
程序员无需像C++中那样手动用delete释放内存。
但是js也有delete关键字,它是用来删除对象的属性,或者删除数组中的指定元素。并不能删除对象本身。用法如下:
语法
delete objectName.propertydelete objectName[index]delete property
参数
objectName
要删除属性或元素的对象。
property
要删除的属性。
index
要删除的数组元素的序号。

第三种用法delete property只能在 with 语句中使用,用来删除对象的属性。补充:在微软的JScript中有CollectGarbage()函数可以用来回收内存,官方文档不推荐使用此方法,你的程序不应该依赖此方法。IE在最小化的时候会进行回收内存。

JavaScript中的传值与传引用

1.传值(by value)
变量的值被复制出一份,与原来的值将不相干,也就是说即使新的值被修改,原来的值也不会改变,在JavaScript中基本类型都是传值的.
function testPassValue()
{
var m=1;
var n=2;

//将m,n的值复制一份,传递到passValue
passValue(m,n);

alert(m); //将是原有的值
}

function passValue(a,b)
{
a = a+b; //改变a的值,这里a只是原有值的一份copy
alert(a); }输出结果:31
2.传引用(by reference).
引用本身复制一份传给function,引用指向的对象并没有被复制传递(java中也是如此),在function中,如果改变了对象的属性的值,由于和原来的引用指向的是同一个对象,因此在通过原来的引用访问到的将是修改过的值;
但是如果只是在function中将引用指向一个新的对象,将不会改变原对象的值,改变的只是复制的这一份引用.
function testPassValue()
{
var date = new Date(2006,02,27);
alert(date.getDate()); //输出为 27

//将date引用本身复制一份,传递到passReference,注意date所指向的对象并没有被复制
passReference(date);
alert(date.getDate()); //输出为12

//同上
changeReference(date);
alert(date.getDate()); //输出还为12
}
function passReference(da)
{
//由于da和原引用指向的是同一个对象,在function外,通过原有的引用访问到的将是对象的日期属性值,将是修改之后的值.
da.setDate(12);
}
function changeReference(da)
{
//此时da引用实际上是原引用的一份copy,将引用本身重新赋值,将不会影响原引用
da= new Date(2007,05,11);
//将da引用指向一个新的对象,此时原引用指向的还是原来的对象
alert(da.getDate()); // 输出为11

}

3 特殊的String
在JavaScript中,String也传引用的. js中只有charAt方法,而没有对应的修改方法,和java中的String相同,都具有不变性.
var s1 = "hello";

var s2 = "hell" + "o";

if (s1 == s2)
alert("s1 = s2"); //这句会不会执行? java用的熟的人可能会认为不会执行,因为java中的==比较的是同一性. 事实上在js中对String==比较的是值是否相等,所以这句话会执行. 但是对其他的Object == 比较和java中一样是同一性