1.Javascript的闭包,说闭包离不了作用域,先看看作用域:
先贴点基本代码:
var n=110;
function funA(){
alert(n);
}
funA(); // 弹出结果:110 结果很正常,声明一个函数外部的变量,访问,弹出结果。
// 局部变量
function funB(){
var nn=5;
}
alert(nn); // error 提示nn未定义;
再看下一个:
function funC(){
myNumber=998;
}
funC();
alert(myNumber);
这个会弹出什么结果?error?额,这个结果却是998了。。。与上一个的完全不同,这就是var关键字的作用了,如果在函数内部声明局部变量一定要带上var关键字,否则解释的时候在就被当做全局变量了,现在的myNumber就已经是全局变量了,所以可以访问到,而上个funB()中因为有关键字var的限制,参数是局部变量,函数外部无法访问到内部的局部变量,所以会出现错误。总的来说就是变量作用域照成的结果。
2.如果我想访问funB中的局部变量怎么办?
这时候可以这个样子,在funB方法中再做一些东西,如下:
function funB(){
var nn=5;
funD=function(){
alert(nn);
}
}
这样funD就可以访问到funB的局部变量nn了,对funD来说,funB父级内的都是可以访问的,而funB则无法访问funD中的内容,这就是Javascript的“链式作用域”结构(chain scope)所决定的。所以只要在funB中返回funD的结果,那么在funB函数外就可以调用funD()了。
function funB(){
var nn=5;
function funD(){
alert(nn);
}
return funD;
}
funB();// 弹出 结果5;
3.闭包:
funD其实就是闭包(一个子函数),通过函数内部的子函数来访问局部变量,在函数内部和函数外部连接起来的一座桥梁,将变量的访问范围扩大但又不会破坏变量作用域安全的这一效果.
4.闭包的用途
下面是闭包的一个例子:
function funMain(){
var n=999;
nSet=function(value){
n+=value;
}
function fSon(){
alert(n);
}
return fSon;
}
var result=funMain(); //对funMain的返回结果fSon的引用
result(); // 第一次调用这就直接返回fSon 结果:999
nSet(1000);// 注意nSet没有使用关键字var
result(); // 第二次调用结果:1999;
这是demo中多了个nSet的匿名函数,而且这个nSet是funMain的子函数,所以nSet也是一个闭包,nSet没有关键字var,所以nSet可以直接在父函数外直接访问。第二次输出结果是1999,那么父函数中的局部变量n并没有在funMain第一次被调用完后就销毁,因为一直存在一个叫result的对funMain变量的引用,直到result被GC回收,然后funMain才会被回收。
5.注意事项:
上个例子中的nSet可以在外部对函数的局部变量进行操作。那么这个就存在一定的危险了,它可以在外面修改父函数的局部变量,而且对父函数的变量一直引用消耗浏览器内存,对于内存的消耗是比较好处理的,只需要删除不必要的引用,标记delete就可以了。
对于在外部修改函数局部变量的问题,利用OO,把父函数当对象进行处理,这种闭包当做OO中的public属性,局部变量当做私有属性来处理会好一点,风险还是有的.
PS:木有胆量,那来产量!