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就是个大闭包。
檬帝,能解释下面这个代码是哪个引用引个么?都是叫i,能画个图么?
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);
}
for(var i=0,l=li.length;i<l;i++){
li[i].onclick=(function(_i){
return function(){alert(_i);}
})(i);
}
li[i].onclick=(function(i){
return function(){alert(i);}
})(i);
相当于
var func=function(_i){
var fn=function(){alert(_i);}
return fn;
}
var callback=func(i);
li[i].onclick=callback;
li的onclick事件调用了callback,而callback又引用了func里面的函数,形成了闭包。由于闭包使得i被保存在闭包函数中
很好很给力,檬檬!
柠檬很给力,我表示对这个example相当有好感