# # #闭包的定义:
>当函数可以记住并访问所在词法作用域时,就产生了闭包,即使函数是在当前词法作用域外执行(《你不知道的js》的解释);
我得个人理解:b 当函数嵌套时,内层函数访问了外层函数的内容是变会产生闭包,可以通过google浏览器调试观察
例如:
```
function foo(){
var a=2;
function bar(){
console.log(a);//2
}
return bar;
}
var baz=foo()()//2,这就是闭包的效果
```
bar在foo内声明,并且作为foo的返回值,而且引用了foo作用域内的a,所以在foo执行完时,foo作用域不能被垃圾回收器回收,作用域一直存在,如果向被回收,可以将baz=nul,因为必报的接收值时baz;
# # #闭包的用途:
> 提供数据缓存,
例:
```
for(var i=0;i<=5;i++){
setTimeout(function timer(){
console.log(i);
},1000);
}
```
以上代码会输出6个6,因为定时器会将其内部函数放入异步队列,是宏任务,后续更,所以会等for循环完才会触发回调函数,这时候需要数据缓存来输出每次i的值,就用到闭包了
```
for(var i=0;i<=5;i++){
(function(j){
setTimeout(function timer(){
console.log(j);
},1000)
})(i);
}
```
我们通过在t定时器外嵌套一层自执行函数。i作为参数传入,被timer函数调用,从而形成了闭包,实现了数据缓存的功能。以上会输出012345;这里不考虑es6的let,let i将for内的作为一个块级作用域相当于每次循环都创建一个作用域,回调的时候是一次调用let创建的作用域
终极闭包题:
```
function fun(n,o){
console.log(o);
return {
fun:function(m){
return fun(m,n);
}
}
}
var a=fun(0);a.fun(1);a.fun(2); a.fun(3);//undefined 0 0 0
var b=fun(0).fun(1).fun(2).fun(3);//undefined 0 1 2
var c=fun(0).fun(1);c.fun(2);c.fun(3);//undefined 0 1 1
```
对于undefined,o被打印的时候并没有值,所以刚开始都是undefined
> a: a是fun(0)的接收者,存储的是fun(0)中的闭包,也就是0,后面a.fun()调用多少次,传的是什么。a中存储的永远是f(0)产生的闭包也就是0;return fun(m,n)时调用了n,此时传入的n的值是0,所以闭包中n的值是0
> b: b是fun连续调用,每次输出的都是上次闭包的缓存值,所以会输出undefined,0,1,2;
> c: c存储的fun(0).fun(1)中n的值,此时n是1,刚开始先是输出undefined,0,1,此时闭包中n的值就是1,所以后面无论怎么调用,都会输出1,因为闭包中n的值不会变了