首先我说一下对闭包的理解:简单的来说他就是函数内部和函数外部连接的一座桥梁使函数外部能够访问到函数内部的值。
因为js特有的‘链式作用域’结构(chain scope),函数内部可以访问函数外部的值,子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
所以我们想让外部看到我们内部的值就需要通道闭包啦!
简单举个例子:
function f1(){
n=5; //不加var函数里面叫隐式全局变量,当在外部调用这个函数时就可以被访问到
}
f1();
console.log(n); //5
当我们在函数内部给n加上var时,即使向上面那样外部调用我们也无法获得n这时就需要用到我们的闭包了。
function f1(){
var n=5; //加上var定义了一个局部变量,即使函数在外部调用时也访问不到,这时我们就需要用闭包来使外部函数访问到他
f2=function(){
console.log(n);
n++;
}
return f2;
}
var a=f1(); //这时a得到了f1函数返回的内部函数f2
a(); //5
a(); //6 再次调用时直接打印的是6(实际上这时n的值已经成为了7),这时又引出了闭包的另一个用处,在函数调用完成后内存不会被释放
在这有一个小题目可以和大家分享一下,看看我们是否真正理解了闭包:看一下下面这个问题,add(1)和add(2)分别输出的是什么
var a=6;
var b=9;
function add(a){
add=function (b){
console.log(++a + b++);
}
console.log(a++);
}
add(1);
add(2);
---------------------------------------------------------------------------------------------------------------------------------------------
公布答案:
add(1) //1
add(2) //5
分析:首先顶部的那个俩全局变量啥用都没有,是用来迷惑人的,我们直接忽略
首先执行add(1)这时形参a为1 console.log(a++);因为是a++所以先打印出来1(这时a已经变成了2)
然后执行add(2)这时执行的就是我们函数内部的那个add函数,传过去的参数为2,即b=2
然后执行console.log(++a + b++);
因为刚刚a已经成为2了 所以++a=3
++a + b++(2)=5
最后说一下使用闭包应该注意的:
1.闭包会使得函数中的变量都被保存在内存中,不会被垃圾回收机制自动清除,所以滥用闭包可能会造成内存泄露,对网页的性能也有很大影响
2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值。