javascript真是神奇的语言,实在是太灵活了。

javascript中的变量,大体分为两大种。 “直接量”和”引用量”,姑且这么称呼吧,肯定不标准。

:)

“直接量”包括,number,string,boolean

除此之外,都是”引用量”

有很多JS的面试题,都在这里搞点花样。

var a=[1,2,3];

var b=a;

a[0]=2;

console.log(b[0]);

结果:2

深入的理解这段代码。

var a=[1,2,3];

var b=a;

看起来似乎是把数组赋值给a了,其实不然,应该是a引用了数组[1,2,3] , 可以这么理解。内存中存在了一个数组[1,2,3],而变量a其实只是保存了一个对数组[1,2,3]的引用罢了。

那么,b=a就好理解了,b只是复制了这种引用。

所以a[0]的重新赋值,会让b[0]也随着改变。 因为a和b本来就引用了同一个数组。

而如果是直接量的,就不会存在这样的情况。

var a=”hello”;

var b=a;

a=1;

console.log(b);

结果:hello

———————————————————————————————————

有的时候,需要复制而不是引用,就麻烦了。

var a={attr:1};

如果需要复制一个a。。怎么办呢?

function copy(o){

var obj={};

for(var i in o){

obj[i]=o[i];

}

return obj;

}

没错,生成一个对象,然后把被复制的对象的所有属性都拷贝一份到新的对象里。。

当然,如果你要拷贝一个数组,就要new一个Array,拷贝一个function,就要new一个Function,

————————————————————————————————————————————–

引用,各种引用,各种各种引用,JS就是由引用组成的。

获取DOM对象,是引用,填充数组还是引用。使用直接量的机会对于JS来说,是那么的稀少。 :(

这就引入了又一个奇怪的货色:闭包,引用的副产品。

所谓的闭包,一句话讲,就是函数外引用了函数内的局部变量(或者叫私有变量吧,反正都是一回事 :]  )。

举例:

var b;

function closure(){

var i=0;

b=function(){i++;alert(i);}

}

closure();

b();

b();

在上例中,全局变量b引用了函数closure中的匿名函数,这就形成了一个闭包。

说起闭包,就要说JS的内存回收,JS的内存回收机制是,如果有一个东西,不存在被引用,就会被销毁回收。(销毁的过程是怎么样的,是立刻回收还是有个时间间隔,没有测试过,欢迎讨论),换言之,如果被引用,那么就会驻留在内存中,不被回收,正式由于JS得这个特性,使得闭包得以存在。

由于变量b引用了函数中的内部变量,使得closure无法被回收,然后它的所有一切都被保存下来,包括内部变量i

在这个例子中,运行b,第一次是1,第二次是2,就是这个道理了。

于是,闭包的好处出现了——可以保存变量,坏处也出现了——–内存泄露

在循环给DOM元素绑定事件中,经常会用到闭包。

var li=document.getElementsByTagName(“li”);

for(var i=0,l=li.length;i<l;i++){

li[i].onclick=function(){alert(i);}

}

在上例中,按照代码理解,应该是每个li在点击的时候alert出这个li的索引。但是事与愿违,alert出的总是最后一个

因为,虽然每个li都绑定了onclick事件,但是等到click事件执行的时候,变量i已经是l了

这时候闭包出场了。。

var li=document.getElementsByTagName(“li”);

for(var i=0,l=li.length;i<l;i++){

li[i].onclick=(function(i){

return function(){alert(i);}

})(i);

}

事实上给li绑定的函数,引用了匿名函数的内部变量。。形成了闭包,使得当时的i也被保存了下来。

———————————————————————————————————–

虽然有如此好处,闭包依然尽量避免,不仅仅是可见的内存泄露,更多的时候,闭包会不自觉的形成循环引用,造成更大的问题。

:) 不过Jquery就是个大闭包。